Main Content

Const rvalue reference parameter may cause unnecessary data copies

The const-ness of an rvalue reference prevents intended move operation

Since R2021a

Description

This defect occurs when a function takes a const rvalue reference as parameter. For instance, this move constructor takes a const rvalue reference:

class aClass {
   public:
     aClass (const aClass&& anotherClass);
}

Risk

The const nature of the rvalue reference parameter prevents the expected move operation.

For instance, this issue can happen when you write a move constructor by copy-paste from a copy constructor with a const parameter, for instance:

aClass (const aClass& anotherClass);
After the copy-paste, you might modify the & to && but forget to omit the const in the reference or the copy operations in the constructor body. In this case, the move constructor with the const rvalue reference compiles without errors but leads to an inefficient move constructor that actually copies the data.

Fix

Remove the const qualifier from the rvalue reference parameter.

For instance, the move constructor in the preceding section can be rewritten as:

class aClass {
   public:
     aClass (aClass&& anotherClass);
}
You might also want to check the move constructor body and make sure that you are actually moving the data and not copying.

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

Examples

expand all

#include <string>
#include <utility>

class Task {
    public:
       Task( const Task& ) = delete;
       Task( const Task&& other ) noexcept; 
    private:
       std::string m_name;
       bool m_is_pending = false;
};

In this example, the move constructor has a const rvalue reference, which causes the defect.

The defect could have been introduced because the move constructor was created by copy-paste from the copy constructor that is deleted here.

Correction – Remove const from Parameter

Remove the const qualifier from the move constructor parameter to allow mutation of the parameter within the constructor body.

#include <string>
#include <utility>

class Task {
    public:
       Task( const Task& ) = delete;
       Task( Task&& other ) noexcept; 
    private:
       std::string m_name;
       bool m_is_pending = false;
};

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: CONST_RVALUE_REFERENCE_PARAMETER
Impact: Low

Version History

Introduced in R2021a