我们来看下面的C ++示例:
#include <iostream>
struct X
{
std::string s;
X() : s("X") { }
X(const X& other) : s{other.s} { std::cout << "cpy-ctor\n"; }
X(X&& o): s{o.s} { o.s = ""; std::cout << "move-ctor\n"; }
X& operator=(const X& other) {
std::cout << "cpy-assigned\n";
s = other.s;
return *this;
}
X& operator=(X&& other) {
if (this != &other) {
s = other.s;
other.s = "";
}
std::cout << "move assigned\n";
return *this;
}
};
X f(X x) {
std::cout << "f: ";
return x;
}
X g() {
std::cout << "g: ";
X x;
return x;
}
int main() {
X x;
X y;
x = f(X());
y = g();
}
如果我用gcc 4.8.2编译它,我得到以下结果:
f: move-ctor
move assigned
g: move assigned
我不明白为什么在调用g函数时没有调用copy-constructor。
我只是想了解何时调用复制或移动构造函数。
答案 0 :(得分:1)
在C ++中,所有表达式都是:
X x{};
Y y{x}; // copy constructor, x is an lvalue
使用RVO,默认情况下由gcc启用。这样就可以使用复制构造函数,而是构造一次对象。
X g()
{
X x {};
x.value = 10;
return x;
}
X y {g()}; // X constructor get's called only once to create "y". Also
// y is passed a a reference to g() where y.value = 10.
// No copy/move constructor for optimization "as if" rule
没有RVO,在这种情况下取决于它。如果显式或隐式删除了移动构造函数,那么它将调用复制构造函数
复制构造函数
struct X { X(const X&) {}}; // implicitly deletes move constructor
// and move assignment, see rule of 5
X g()
{
return X{}; // returns a prvalue
}
X y {g()}; // prvalue gets converted to xvalue,
// "temporary materialization", where the xvalue has an
// identity where members can be copied from. The xvalue
// binds to lvalue reference, the one from copy constructor
// argument
移动构造函数
X { X(X&&) {}}; // explicitly declared move constructor
X g()
{
return X{}; // returns a prvalue
}
X y {g()}; // prvalue gets converted to xvalue,
// "temporary materialization", where the xvalue has an
// identity where members can be moved from. The xvalue
// binds to rvalue reference, the one from move constructor
// argument
X x {};
X y {std::move(x)}; // std::move returns an xvalue, where if move
// constructor is declared will call it, other wise
// copy constructor, similar to explained above for
// prvalue.
X x{};
X y{};
x = y; // call copy assignment operator since y is an lvalue.
如果显式或隐式删除移动分配,则它将调用复制赋值运算符。
复制作业
struct X{ X& operator=(const X&); } // implicilty deletes move
// constructor and move assignment,
// see rule of 5
X g()
{
return X{}; // returns a prvalue
}
x = y; // prvalue gets converted to xvalue,
// "temporary materialization", where the xvalue has an identity
// where members can be copied from. The xvalue binds to lvalue
// reference, the one from copy assignment operator argument
移动作业
struct X{ X& operator=(X&&); } // explicitly declared move assignment operator
X g()
{
return X{}; // returns a prvalue
}
x = y; // prvalue gets converted to xvalue,
// "temporary materialization", where the xvalue has an identity
// where members can be moved from. The xvalue binds to rvalue
// reference, the one from move assignment operator argument
X x {};
X y {};
x = std::move(x); // std::move returns an xvalue, where if move
// assignment is declared will call it, other
// wise copy assignment, similar to explained
// above for prvalue.
答案 1 :(得分:0)
使用同一类型的另一个对象实例化对象时,将调用复制构造函数。
例如:
X x;
X y(x);
代码中的最后一行将函数返回的值赋给已构造的对象。这是通过移动分配完成的。