以下代码是否正常
#include <iostream>
struct Foo
{
Foo() { std::cout << "Foo::Foo" << std::endl; }
~Foo() { std::cout << "Foo::~Foo" << std::endl; }
Foo(const Foo&) { std::cout << "Foo::Foo(const Foo&)" << std::endl; }
Foo& operator=(const Foo&) { std::cout << "Foo::operator=(const Foo&)" << std::endl; return *this; }
Foo(Foo&&) { std::cout << "Foo::Foo(Foo&&)" << std::endl; }
Foo& operator=(Foo&&) { std::cout << "Foo::operator=(Foo&&)" << std::endl; return *this; }
};
Foo foo()
{
Foo second;
return second;
}
int main()
{
foo();
}
产生这样的输出:
Foo::Foo
Foo::Foo(Foo&&)
Foo::~Foo
Foo::~Foo
为什么调用移动构造函数而不是复制构造函数?
答案 0 :(得分:3)
答案很简单,因为标准是这样说的。第12.8节,第32段:
当满足复制/移动操作的省略标准时,但不符合例外声明,并且 要复制的对象由左值指定,或者当返回语句中的表达式为(可能是 parenthesized)id-expression命名一个具有在body中声明的自动存储持续时间的对象 最内层封闭函数或lambda表达式的参数声明子句,重载决策 首先执行选择复制的构造函数,就好像该对象是由右值指定的。
基本上就是这一切。逻辑上,如果变量具有自动存储持续时间,并且您return
它,那么在返回之后,当本地范围清除时,该变量将不再存在。这就是为什么,即使它是左值,它也非常类似于右值。因为它在技术上仍然是一个左值,所以必须在标准中明确地做出这个例外,我们就是这样。请注意,整个情况特定于return
来自函数,并且不包括范围一般结束。