Move-CTOR和COPY-CTOR未调用
Move-ctor and copy-ctor not called
让我们进行以下C 样本:
#include <iostream>
struct X
{
std::string s;
X() : s("X") { }
X(const X& other) : s{other.s} { std::cout << "cpy-ctorn"; }
X(X&& o): s{o.s} { o.s = ""; std::cout << "move-ctorn"; }
X& operator=(const X& other) {
std::cout << "cpy-assignedn";
s = other.s;
return *this;
}
X& operator=(X&& other) {
if (this != &other) {
s = other.s;
other.s = "";
}
std::cout << "move assignedn";
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函数时未调用复制构建器。
我只是想了解何时调用副本或移动构造函数。
尽管您是正确的,可以从逻辑上确定返回g()
的局部变量x
的副本/移动,但是C 的有用功能是它可以 elide (即跳过(在许多情况下,即使复制/移动将具有副作用,也是如此。这是其中一种情况。执行时,这被称为命名的返回值优化。
可以说,它比我们移动语义之前的有用性要少,但是仍然很高兴。实际上,C 17在某些(选择(案例中必须进行强制性。
在C 中所有表达式均为:
- lvalue
- prvalue
- xvalue
构建对象
-lvalue
Y x{};
Y y{x}; // copy constructor, x is an lvalue
-prvalue -RVO
使用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
- prvalue -no rvo
没有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
-xvalue
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.
复制/移动分配
-lvalue
X x{};
X y{};
x = y; // call copy assignment operator since y is an lvalue.
-prvalue
如果移动分配是明确或隐式删除的,则将调用复制分配运算符。
复制分配
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 = 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 assignment operator argument
移动分配
struct X{ X& operator=(X&&); } // explicitly declared move assignment operator
X g()
{
return X{}; // returns a prvalue
}
x = 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 assignment operator argument
-xvalue
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.
当您使用同一类型的另一个对象实例化对象时,将调用复制构造函数。
例如:
X x;
X y(x);
代码中的最后一行分配了一个从函数返回到已经构造的对象的值。这是通过移动分配完成的。
相关文章:
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 复制初始化:为什么即使关闭了复制省略,也没有调用move或copy构造函数
- 调用了Copy ctor而不是move ctor
- 为什么部分初始化一个类然后调用委托 ctor 失败?
- 为什么调用不明确的 ctor 时没有编译时错误?
- 为什么编译器在调用 move 后选择复制 ctor
- 如何调用模板类的模板CTOR
- 是否应在调用基本CTOR时复制继承的构造函数
- Move-CTOR和COPY-CTOR未调用
- 警告在 std::move'ing 时调用复制 ctor
- 当使用类型为"类&&"的变量作为参数时,为什么调用复制 ctor 而不是移动 ctor
- C++11:调用移动 ctor/operator= 时
- 代码调用复制 ctor 通常必须调用移动 ctor
- 复制列表初始化是否在概念上调用复制 ctor
- 为什么不从临时对象中调用move ctor进行构造(运算符+的结果)
- std::move( ) 在没有 move-ctor 的情况下调用 copy-ctor.为什么以及如何预防它
- C++11:为什么在这里调用复制ctor
- 调用模板ctor时未解析的外部符号
- Init.当COPY CTOR是私有的时候
- C++在使用运算符=()时使用copy ctor-这正是如何工作的