C++14 中的 RVO 和删除的移动构造函数
RVO and deleted move constructor in C++14
最近几天我一直在学习 (N)RVO。正如我在复制省略文章中阅读 cppreference 时,对于 C++14:
... the compilers are permitted, but not required to omit the copy- and move- (since C++11)construction of class objects even if the copy/move (since C++11) constructor and the destructor have observable side-effects. This is an optimization: even when it takes place and the copy-/move-constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed.
因此,复制 或 移动构造函数必须存在且可访问。但是在下面的代码中:
#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.
P.S。我知道在 C++17 标准中 RVO 是有义务的。但是 NRVO 不是,所以我想研究一下这里发生了什么,以了解我什么时候可以使用 NRVO。
引自cppreference:
Deleted functions
If, instead of a function body, the special syntax = delete ; is used, the function is defined as deleted.
...
If the function is overloaded, overload resolution takes place first, and the program is only ill-formed if the deleted function was selected.
如果明确定义要删除的move构造函数就不一样了。这里因为这个删除的移动构造函数的存在,虽然复制构造函数可以匹配,但是移动构造函数更好,因此在重载决策时选择了移动构造函数。
如果删除显式 delete
,则会选择复制构造函数并编译您的程序。
最近几天我一直在学习 (N)RVO。正如我在复制省略文章中阅读 cppreference 时,对于 C++14:
... the compilers are permitted, but not required to omit the copy- and move- (since C++11)construction of class objects even if the copy/move (since C++11) constructor and the destructor have observable side-effects. This is an optimization: even when it takes place and the copy-/move-constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed.
因此,复制 或 移动构造函数必须存在且可访问。但是在下面的代码中:
#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.
P.S。我知道在 C++17 标准中 RVO 是有义务的。但是 NRVO 不是,所以我想研究一下这里发生了什么,以了解我什么时候可以使用 NRVO。
引自cppreference:
Deleted functions
If, instead of a function body, the special syntax = delete ; is used, the function is defined as deleted.
...
If the function is overloaded, overload resolution takes place first, and the program is only ill-formed if the deleted function was selected.
如果明确定义要删除的move构造函数就不一样了。这里因为这个删除的移动构造函数的存在,虽然复制构造函数可以匹配,但是移动构造函数更好,因此在重载决策时选择了移动构造函数。
如果删除显式 delete
,则会选择复制构造函数并编译您的程序。