C 11 未调用移动构造函数,首选默认构造函数
使用 C 中的类时,预计将使用移动构造函数高效的资源转移。但是,在某些情况下,可能会意外选择默认构造函数。
问题陈述
考虑以下类:
<code class="cpp">class X { public: explicit X(char* c) { cout << "ctor" << endl; init(c); } X(X& lv) { cout << "copy" << endl; init(lv.c_); } X(X&& rv) { cout << "move" << endl; c_ = rv.c_; rv.c_ = nullptr; } const char* c() { return c_; } private: void init(char* c) { c_ = new char[strlen(c) + 1]; strcpy(c_, c); } char* c_; };</code>
With示例用法:
<code class="cpp">X x("test"); cout << x.c() << endl; X y(x); cout << y.c() << endl; X z(X("test")); cout << z.c() << endl;</code>
预期输出为:
ctor test copy test ctor move test
但是,最后一行意外输出“ctor”而不是“move”。
说明
根据 C 11 标准,在某些情况下应该调用移动构造函数。在这种情况下,当用 X("test") 构造 z 时应该发生移动。但是,会调用默认构造函数。
此行为是由于复制省略造成的,这是一种优化技术,允许编译器直接将临时对象构造到目标中,而无需执行复制或移动操作。此优化适用于编译器确定复制/移动操作是不必要的并且可以省略的情况。
在给定场景中,编译器认为临时 X("test") 是复制省略的候选者,因为它是在同一个表达式中自动创建和销毁的。因此,它省略了移动操作并直接使用临时数据构造 z,从而导致调用默认构造函数。
结论
复制省略可能会导致意外的结果使用移动构造函数时的行为,因为它可以防止在预期的情况下调用移动构造函数。编译器可以根据其优化启发式应用复制省略,这可能因编译器和优化设置而异。了解复制省略及其对程序行为的潜在影响非常重要。
以上是为什么启用复制消除后,C 11 中未调用移动构造函数?的详细内容。更多信息请关注PHP中文网其他相关文章!