コンパイル:g ++ --std = c ++ 11 -g -fno-elide-constructors -O0 test.cc -o test
-fno-elide-constructorsは、コンパイラの最適化をオフにするために使用されます
#include <iostream>
class A {
public:
A(const int &value) {
_value = value;
std::cout << "Contructor value: " << _value << std::endl;
}
~A() {
std::cout << "Destructor value: " << _value << std::endl;
}
// 拷贝构造函数
A(const A &a) : _value(a._value) {
std::cout << "Copy Contructor value: " << _value << std::endl;
}
// 移动构造函数
A(A &&a) : _value(a._value) {
std::cout << "Move Contructor value: " << _value << std::endl;
}
private:
int _value;
};
-
移動コンストラクターが定義されている場合:
- 最初の状況:
A test() { A a(10); return a; } int main(void) { A a = test(); return 0; }
結果をコンパイルして実行します。
Contructor value: 10 Move Contructor value: 10 Destructor value: 10 Move Contructor value: 10 Destructor value: 10 Destructor value: 10
- 2番目のケース:
A test() { A a(10); return a; } int main(void) { A &&a = test(); return 0; }
結果をコンパイルして実行します。
Contructor value: 10 Move Contructor value: 10 Destructor value: 10 Destructor value: 10
- 3番目のケース:
A &&test() { A a(10); return std::move(a); } int main(void) { A &&a = test(); return 0; }
結果をコンパイルして実行します。
Contructor value: 10 Destructor value: 10
- 4番目のケース:
A &&test() { A a(10); return std::move(a); } int main(void) { A a = test(); return 0; }
結果をコンパイルして実行します。
Contructor value: 10 Destructor value: 10 Move Contructor value: -374511968 Destructor value: -374511968
- 5番目の状況:
A &&test() { A a(10); return std::move(a); } int main(void) { A a = test(); return 0; }
結果をコンパイルして実行します。
Contructor value: 10 Destructor value: 10
-
移動コンストラクターを定義しない場合:
- 同じ5つのケースの結果は次のとおりです。
Contructor value: 10 Copy Contructor value: 10 Destructor value: 10 Copy Contructor value: 10 Destructor value: 10 Destructor value: 10
Contructor value: 10 Copy Contructor value: 10 Destructor value: 10 Destructor value: 10
Contructor value: 10 Destructor value: 10
Contructor value: 10 Destructor value: 10 Copy Contructor value: -298764640 Destructor value: -298764640
Contructor value: 10 Destructor value: 10
クラスにコピーコンストラクターと移動コンストラクターの両方が含まれている場合、一時オブジェクトを使用して現在のクラスのオブジェクトを初期化すると、コンパイラーは最初に移動コンストラクターを呼び出してこの操作を完了します。クラスに適切な移動コンストラクターがない場合にのみ、コンパイラーが2番目の場所を取り、コピーコンストラクターを呼び出します。
デフォルトでは、同様のオブジェクトの左辺値の初期化は、コピーコンストラクターを介してのみ実行できます。移動コンストラクターを呼び出す場合は、初期化に右辺値を使用する必要があります。C ++ 11標準では、moveコンストラクターを使用して同様のオブジェクトを左辺値で初期化するユーザーのニーズを満たすために、左辺値を対応する右辺値に強制できるstd :: move()関数が新しく導入されました。次に、moveコンストラクターを使用できます。