[英]Move semantics in C++11
我想充分理解C ++ 11中的移動語義。 因此,我編寫了幾個類來查看何時調用不同的構造函數:
#include <iostream>
using namespace std;
class A {
public:
A() : a1_(0) {std::cout << "Calling constructor" << std::endl;}
A(A&& other) {
std::cout << "Calling move constructor" << std::endl;
a1_ = other.a1_;
other.a1_ = 0;
}
// Move assignment operator.
A& operator=(A&& other) {
std::cout << "Calling move operator" << std::endl;
if (this != &other) {
a1_ = other.a1_;
other.a1_ = 0;
}
return *this;
}
// Copy constructor.
A(const A& other) {
std::cout << "Calling copy constructor" << std::endl;
a1_ = other.a1_;
}
// Copy assignment operator.
A& operator=(const A& other) {
std::cout << "Calling copy assignment operator" << std::endl;
if (this != &other) {
a1_ = other.a1_;
}
return *this;
}
private:
int a1_;
};
class B {
A oA_;
public:
B() {}
void setoA(A a) {oA_ = a;}
A getoA() {return oA_;}
};
A createA() {
A a1;
return a1;
}
B createB() {
B tmpB;
A tmpA;
tmpB.setoA(tmpA);
return tmpB;
}
int main() {
B b;
A a;
b.setoA(a);
std::cout << "**************************" << std::endl;
b.setoA(createA());
std::cout << "**************************" << std::endl;
b.setoA(std::move(createA()));
std::cout << "**************************" << std::endl;
B b2;
b2.setoA(b.getoA());
std::cout << "**************************" << std::endl;
createB();
return 0;
}
當我檢查此代碼的輸出時:
Calling constructor Calling constructor Calling copy constructor Calling copy assignment operator ++++++++++++++++++++++++++++++++++ Calling constructor Calling copy assignment operator ++++++++++++++++++++++++++++++++++ Calling constructor Calling move constructor Calling copy assignment operator ++++++++++++++++++++++++++++++++++ Calling constructor Calling copy constructor Calling copy assignment operator ++++++++++++++++++++++++++++++++++ Calling constructor Calling constructor Calling copy constructor Calling copy assignment operator
我在這里有一些疑問:
我以為如果傳遞r-value
,就會調用move構造函數,對嗎? 這不是b.setoA(createA());
r-value
?
如何使移動構造函數/運算符被調用?
首先在第一節中,為什么構造函數被調用兩次?
因為你既構建一個B
和A
與前者有其自身的實例A
,其中第(意外)構造函數調用的來源。
我以為如果通過r值將調用move構造函數,對嗎? 這不是
b.setoA(createA());
一個r值?
構造函數是在createA
(是的,返回值是一個r值),但是,會發生復制省略,並且直接在setoA
的參數變量中實例化該對象。
但是,在setoA
中選擇了副本分配,因為現在a
是一個l值。 如果要移動,則需要:
void setoA(A a) { oA_ = std::move(a); }
編譯器可以選擇刪除某些副本和移動。 為防止這種情況,請在GCC和Clang中使用-fno-elide-constructors
。 另外,一些移動省略在C ++ 17中成為強制性的,因此要強制編譯器使用C ++ 11移動語義, -std=c++11
使用-std=c++11
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.