メインコンテンツ

移動不可能な型で std::move が呼び出される

移動コンストラクターまたは移動代入演算子のないクラス型で std::move が使用される

説明

この欠陥は、移動コンストラクターまたは移動代入演算子が含まれていないクラス型のオブジェクトを std::move を使用して移動した場合に発生します。

リスク

次のようなステートメントでの std::move の使用は、

Obj objTo {std::move(objFrom)};
objTo = std::move(objFrom);
移動操作のパフォーマンスを向上させようとする意図を表します。ただし、移動コンストラクターまたは移動代入演算子が欠落しているため、代わりにコピー操作が実行されます。

クラスのコピーの計算量が多い場合は、意図しないコピー操作によってパフォーマンスが低下する可能性があります。

修正方法

T 型のオブジェクトを移動可能にするには、次の移動コンストラクター

T (T&&);
と次の移動代入演算子
T& operator=(T&&);
をクラス T に追加します。クラスで直接リソースを管理する必要がない場合は、次のように、=default 構文を使用してコンパイラ生成移動演算子を使用できます。
T (T&&) = default;

または、移動操作が必要ない場合は、std::move 呼び出しを削除して、直接オブジェクトをコピーします。

パフォーマンスの改善の程度は、使用しているコンパイラ、ライブラリ実装、環境によって異なる可能性があります。

すべて展開する

#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);
}

この例では、stringPair 型に移動コンストラクターまたは移動代入演算子が含まれていません。この型のオブジェクトに対して std::move を使用すると、代わりにコピー操作が実行されます。

修正 – 移動コンストラクターと移動代入演算子を追加

移動コンストラクターまたは移動代入演算子を追加することによって、stringPair 型を移動可能にします。

#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);
}
修正 — std::move 呼び出しを削除

stringPair 型を移動可能にしない場合は、std::move 呼び出しを省略します。

#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;
}

結果情報

グループ: パフォーマンス
言語: C++
既定値: オフ
コマンド ライン構文: STD_MOVE_UNMOVABLE_TYPE
影響度: Medium

バージョン履歴

R2020b で導入