Main Content

Expensive last use of variable

An expensive-to-copy local variable is copied in its final use instead of being moved

Since R2025a

Description

Polyspace® reports this defect when both of these conditions are true:

  • The final use of a local variable in its scope is a copy operation.

  • It is less expensive to move the variable than it is to copy it.

Risk

If a variable is expensive to copy, then copying the variable on its last use in its scope provides no benefit and makes the code inefficient.

Fix

If an expensive-to-copy object is not used later in its scope, use std::move() to move the object instead of copying it on its last use.

Performance improvements might vary based on the compiler, library implementation, and environment that you are using.

Examples

expand all

In this example, several expensive-to-copy local variables are copied to their destinations and then never used again. These copy operations are unnecessary and make the code inefficient. Polyspace reports defects.

#include <string>
#include <set>

struct Employee
{
	std::string name;
	std::string position;
};

bool operator<(const Employee &e, const std::string &k) {
	return e.name < k;
}
bool operator<(const std::string &k, const Employee &e) {
	return k < e.name;
}
bool operator<(const Employee &e1, const Employee &e2) {
	return e1.name < e2.name;
}



static std::set<Employee> employees;

void addEmployee(std::string name, std::string position)
{
	Employee e;

	e.name = name;                              /* Defect */
	e.position = position;                      /* Defect */

	employees.insert(e);                        /* Defect */
}

void addEmployee2(std::string name, std::string position)
{
	Employee e { name, position };              /* Defect */

	employees.insert(e);                        /* Defect */
}

void addEmployee3(std::string name, std::string position)
{
	employees.insert({ name, position });       /* Defect */
}
Correction — Move Local Variables on Last Use

To fix the defects, move the local variables on their last use.

#include <string>
#include <set>

struct Employee
{
	std::string name;
	std::string position;
};

bool operator<(const Employee &e, const std::string &k) {
	return e.name < k;
}
bool operator<(const std::string &k, const Employee &e) {
	return k < e.name;
}
bool operator<(const Employee &e1, const Employee &e2) {
	return e1.name < e2.name;
}



static std::set<Employee> employees;

void addEmployee(std::string name, std::string position)
{
	Employee e;

	e.name = std::move(name);                              /* No Defect */
	e.position = std::move(position);                      /* No Defect */

	employees.insert(std::move(e));                        /* No Defect */
}

void addEmployee2(std::string name, std::string position)
{
	Employee e { std::move(name), std::move(position) };              /* No Defect */

	employees.insert(std::move(e));                        /* No Defect */
}

void addEmployee3(std::string name, std::string position)
{
	employees.insert({ std::move(name), std::move(position) });       /* No Defect */
}

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: EXPENSIVE_COPY_ON_LAST_USE
Impact: Medium

Version History

Introduced in R2025a