这个问题已经在这里有一个答案:
我读STD模板库书,并与STL容器章列举如下细节被搞糊涂了。显然,它指定的std ::向量操作和效果
Operation Effect
vector<Elem> c(c2) | Copy constructor; creates a new vector as a copy of c2 (all elements are copied)
vector<Elem> c = c2 | Copy constructor; creates a new vector as a copy of c2 (all elements are copied)
vector<Elem> c(rv) | Move constructor; creates a new vector, taking the contents of the rvalue rv (since C++11)
vector<Elem> c = rv | Move constructor; creates a new vector, taking the contents of the rvalue rv (since C++11)
显然,没有在语法两个移动和拷贝构造函数没有区别,那到底什么时候他们叫什么名字?
比方说您有一个函数f
按值返回一个向量:
std::vector<int> f();
函数返回值是一个右值。
然后,让我们看看调用这个函数来初始化你的一个向量:
std::vector<int> v = f();
现在,编译器知道通过f
返回的矢量不会被更多的使用,这是一个临时的对象,因此没有意义复制此临时对象,因为它只是被立即反正破坏。因此,编译器决定调用move构造函数来代替。
此举构造函数被调用,其中是有意义的调用它,即移动对象,并用它此后没有意义,与原始对象已被修改(可能的),这是不希望:
std::vector<int> a = { 1 };
std::vector<int> b = a; //Let's say this called move constructor
int value = a[0]; //value is possibly not 1, the value may have changed due to the move
所以,在这种情况下,拷贝构造函数被调用:
std::vector<int> a = { 1, 2 };
std::vector<int> b = a; //Copy constructor
但是,在这里它调用移动的构造,因为它被分配给右值,或临时值:
void foo(std::vector<int>) {}
foo({ 1, 2 }); //move constructor
矢量{ 1, 2 }
是一个临时的载体,谁在乎它是否已被修改?你永远不会知道,作为载体将得到尽快foo
已经结束破坏。复制临时载体也只是浪费时间。
也许你应该脱钩语义语法更好的理解。让我做一个类比,考虑下面的代码。
struct A {
A(int i) {}
A(const std::string& s) {}
};
现在,如果你找到下面的行,其构造函数将被调用?
A a(x);
你不能告诉它,因为你不知道x
是否有类型为int或std ::字符串。这不是在你的例子太多不同,但随着移动语义编译器会检查该参数是右值与否。如果这样的A
类提供了一个(移动)的构造的过载和x
是一个rvalue参考,那么它会是优选的。
显然,有两个移动和拷贝构造函数的语法没有区别
事实上,这是事实。这是不特定于std::vector
要么,但一般适用于所有类型。复制初始化通过复制和移动具有完全相同的语法。这同样适用于拷贝赋值。
的差异来自参数表达式的类型。当参数是一个非const r值,此举构造/分配由过载分辨率是优选的。否则,将构造函数是不适用的,所以拷贝构造函数时使用。
我假定RV就像C2一个构造的对象
休旅车和C2似乎没有对象。他们显然对表达式的占位符。这本书可能是有关更清楚(也许是,摘录是断章取义,毕竟)。
拷贝构造函数的语法:类名(const的类名和)
移动构造函数的语法:类名(类名&&)
调用看起来相同在一起,但他们的声明是不同的。
参考:
http://en.cppreference.com/w/cpp/language/copy_constructor http://en.cppreference.com/w/cpp/language/move_constructor