ムーブコンストラクターとムーブ代入
ムーブコンストラクターとムーブ代入演算子を正しく実装します。
「ムーブコンストラクターとムーブ代入」は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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 左辺値と右辺値の違い
- 右辺値参照と&&構文
- std::moveとstd::forward
- ムーブコンストラクターとムーブ代入