0Pricing
C++ Academy · レッスン

ムーブコンストラクターとムーブ代入

ムーブコンストラクターとムーブ代入演算子を正しく実装します。

「ムーブコンストラクターとムーブ代入」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

2つの特殊メンバー

ムーブコンストラクターとムーブ代入演算子を使うと、コピーせずに別のインスタンスのリソースの所有権をクラスが取得できます。

シグネチャ

どちらも同じ型への右辺値参照を受け取ります。

class String {
public:
    String(String&& other) noexcept;          // move ctor
    String& operator=(String&& other) noexcept; // move assign
};

ムーブコンストラクターの実装

ソースのリソースを奪い、ソースを有効な空の状態にしてください。

String(String&& other) noexcept
    : data_(other.data_), size_(other.size_) {
    other.data_ = nullptr;
    other.size_ = 0;
}

ムーブ代入の実装

手順は3つです。現在のリソースを解放し、ソースのリソースを奪い、ソースを空にします。

String& operator=(String&& other) noexcept {
    if (this != &other) {
        delete[] data_;
        data_ = other.data_;
        size_ = other.size_;
        other.data_ = nullptr;
        other.size_ = 0;
    }
    return *this;
}

noexceptが重要な理由

可能な場合はムーブ操作に noexceptを付けてください。std::vectorのような標準コンテナーは、リサイズ時にムーブ操作が noexceptの場合にのみムーブを使用します。そうでなければ、例外安全性のためにコピーへフォールバックします。

5のルール

次の5つのいずれかを記述する場合は、5つすべてについて検討してください:

  • デストラクター
  • コピーコンストラクター
  • コピー代入演算子
  • ムーブコンストラクター
  • ムーブ代入演算子

0のルール

さらに良い方法は、どれも記述しないことです。メンバーをRAII型(vector、string、スマートポインター)として保持してください。コンパイラーが生成するデフォルトの実装が、正しく効率的に動作します。

class Widget {
    std::string name_;
    std::vector<int> data_;
    // No need for destructor, copy, or move — compiler does the right thing
};

コンパイラーがムーブを生成する場合

コンパイラーがデフォルトのムーブメンバーを生成するのは、次の条件を満たす場合だけです。

  • ユーザーがコピーコンストラクター、コピー代入演算子、デストラクター、またはムーブメンバーを宣言していない
  • すべてのメンバーと基底クラスが、それ自体ムーブ可能である

デフォルト化したムーブと削除したムーブ

コンパイラーが生成するムーブ操作は、明示的に要求したり禁止したりできます。

class Widget {
public:
    Widget(Widget&&) = default;
    Widget& operator=(Widget&&) = default;
    // or
    Widget(Widget&&) = delete;
};

ムーブ後

ムーブ元のオブジェクトは、有効だが未規定の状態になります。次の操作を行えます。

  • 破棄する
  • 新しい値を代入する
  • 事前条件のない操作(size()、empty()、clear())を呼び出す

利用例

ムーブセマンティクスは、次の処理を高速化します。

  • 大きなオブジェクトを返す処理(RVOが適用されない場合)
  • 大きなオブジェクトをコンテナーに格納する処理(右辺値に対するpush_back)
  • 独自のリソース所有型の実装

クイックチェック

ムーブコンストラクターとムーブ代入演算子にnoexceptを付けるべきなのはなぜですか。

まとめ

ムーブコンストラクターとムーブ代入演算子は、まもなく破棄される右辺値からリソースを取得します。コンテナーでの処理を高速化するため、noexceptを付けてください。Rule of Fiveに従うか、標準のRAII型を組み合わせて、より望ましいRule of Zeroを実践してください。

よくある質問

「ムーブコンストラクターとムーブ代入」レッスンは無料ですか?

はい。「ムーブコンストラクターとムーブ代入」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「ムーブコンストラクターとムーブ代入」で何を学びますか?

ムーブコンストラクターとムーブ代入演算子を正しく実装します。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「ムーブコンストラクターとムーブ代入」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 左辺値と右辺値の違い
  2. 右辺値参照と&&構文
  3. std::moveとstd::forward
  4. ムーブコンストラクターとムーブ代入
← C++ Academyに戻る