【发布时间】:2018-02-03 19:12:23
【问题描述】:
过去几天我一直在学习 (N)RVO。正如我在复制省略文章中所读到的 C++14 中的 cppreference :
... 允许编译器,但不需要省略类对象的复制和移动(C++11 起)构造,即使复制/移动(C++11 起)构造函数和析构函数也是如此有明显的副作用。这是一个优化:即使它发生并且 copy-/move-constructor 没有被调用,它仍然必须存在并且可访问(好像没有优化发生在all),否则程序格式错误。
因此,复制 或 移动构造函数必须存在且可访问。但在下面的代码中:
#include <iostream>
class myClass
{
public:
myClass() { std::cout << "Constructor" << std::endl; }
~myClass() { std::cout << "Destructor" << std::endl; }
myClass(myClass const&) { std::cout << "COPY constructor" << std::endl;}
myClass(myClass &&) = delete;
};
myClass foo()
{
return myClass{};
}
int main()
{
myClass m = foo();
return 0;
}
我收到以下错误:test.cpp: In function 'myClass foo()':
test.cpp:15:17: error: use of deleted function 'myClass::myClass(myClass&&)'
return myClass{};。即使我不从main() 调用foo(),我也会收到此错误。 NRVO 也有同样的问题。
因此总是需要移动构造函数,不是吗? (虽然副本不是,但我检查了它)
我不明白编译器在哪里需要移动构造函数。我唯一的猜测是构造临时变量可能需要它,但这听起来令人怀疑。有人知道答案吗?
关于编译器:我在g++和VS编译器上试过,可以在线查看:http://rextester.com/HFT30137。
附:我知道在 C++17 标准中,RVO 是有义务的。但是 NRVO 不是,所以我想研究一下这里发生了什么,以了解何时可以使用 NRVO。
【问题讨论】:
-
使用 gcc 7.2 编译为 C++ 17
-
经验法则:永远不要明确删除移动操作。而是明确定义或删除复制操作,这会抑制移动的生成。唯一显式删除移动操作会产生影响的情况是,您最终会得到一种病态的可复制但不可移动的类型。
-
@Casey,所以,唯一的情况是,当可以删除移动运算符时,是当你删除复制和移动时?或者在这种情况下删除移动操作符是不必要的?
标签: c++ c++14 move-constructor