Main Content

std::move called on an unmovable type

std::move used on a class type with no move constructor or move assignment operator

Since R2020b

Description

This defect occurs when you use std::move to move an object of a class type that does not have a move constructor or move assignment operator.

Risk

The use of std::move in statements such as:

Obj objTo {std::move(objFrom)};
objTo = std::move(objFrom);
indicates that you want to benefit from the performance gains of a move operation. However, because of the missing move constructor or move assignment operator, a copy operation happens instead.

If the class is expensive to copy, the unintended copy operation can cause a loss of performance.

Fix

To make an object of type T movable, add a move constructor:

T (T&&);
and move assignment operator:
T& operator=(T&&);
to the class T. If the class does not have to directly manage a resource, you can use compiler-generated move operators using the =default syntax, for instance:
T (T&&) = default;

Otherwise, if a move operation is not required, remove the std::move call and directly copy the object.

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

Examples

expand all

#include <utility>
#include <string>

class stringPair {
    std::string str1;
    std::string str2;

    public:
        stringPair(const stringPair & aPair); //Copy constructor
        stringPair& operator=(const stringPair & aPair);  //Copy assignment operator
};

void exchangePairs (stringPair& first, stringPair& second) {
    stringPair tempPair {std::move(first)};
    first = std::move(second);
    second = std::move(tempPair);
}

In this example, the type stringPair does not have a move constructor or move assignment operator. Uses of std::move on objects of this type result in copy operations instead.

Correction – Add Move Constructor and Move Assignment Operator

Make the type stringPair movable by adding a move constructor or move assignment operator.

#include <utility>
#include <string>

class stringPair {
    std::string str1;
    std::string str2;
    
    public: 
        stringPair(const stringPair & aPair); //Copy constructor
        stringPair(stringPair && aPair) noexcept; //Move constructor
        stringPair& operator=(const stringPair & aPair);  //Copy assignment operator
        stringPair& operator=(stringPair && aPair) noexcept; //Move assignment operator
};

void exchangePairs (stringPair& first, stringPair& second) {
    stringPair tempPair {std::move(first)};
    first = std::move(second);
    second = std::move(tempPair);
}
Correction –- Remove std::move call

If you do not want to make the type stringPair movable, omit the std::move calls.

#include <utility>
#include <string>

class stringPair {
    std::string str1;
    std::string str2;
    
    public: 
        stringPair(const stringPair & aPair); //Copy constructor
        stringPair& operator=(const stringPair & aPair);  //Copy assignment operator
};

void exchangePairs (stringPair& first, stringPair& second) {
    stringPair tempPair {first};
    first = second;
    second = tempPair;
}

Result Information

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

Version History

Introduced in R2020b