C ++ 11 Standard中的哪个子句支持在下面的函数foo()返回时调用move构造函数?
#include <iostream>
class A
{
public:
A() { std::cout << "Ctor\n"; }
A(const A&) {std::cout << "Copy ctor\n";}
A(A&&) {std::cout << "Move ctor\n";}
};
A foo(A&& ra) { return std::move(ra); }
int main()
{
A a = foo(A());
}
这个问题已被关闭我相信昨天,现在它被“搁置”了,结束的原因是它过于本地化了。我很难理解SO中关于C ++ 11标准的特定问题的帖子如何被认为是“过于本地化”。对我而言,这是一个矛盾,因为标准是“事实上”每个C ++程序员应该寻找的最终文档,如果对语言有疑问的话。
答案 0 :(得分:3)
关于代码有很多条款。特别是初始化(第8节的后面),重载解析(第13节)以及更基本的第3和第5条,以理解表达式和引用类型的值类别。
首先,表达式A()
是由默认构造临时结果产生的类prvalue。
它通过直接引用绑定初始化右值引用ra
。
ra
通过直接引用绑定初始化move
的参数,move
返回类型为A
的xvalue,再次通过直接引用绑定初始化,初始化返回值foo
,通过重载解析到移动构造函数,将第一个临时值移动到foo
的返回值,也是临时值。
表达式foo(A())
是引用第二个临时表的类prvalue。
这通常会通过重载初始化a
来解析移动构造函数的prvalue,并从a
的返回值移动构造foo
- 但是由于12.8 / 32p3 :
当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过直接构造临时对象来省略复制/移动操作进入省略的复制/移动目标
因此,foo
的返回值通常直接在a
的存储中构造,并且省略了第二次移动构造。