让我们有一个带有移动构造函数的类A
。考虑一下:
A get()
{
A a;
return std::move( a );
}
// later in the code
A aa = get();
这里对std:move
的显式调用强制调用A
的移动构造函数,因此它可能会在调用get()
时禁止返回值优化。因此,据说get()
的更好实现是这样的:
A get()
{
A a;
return a;
}
但是返回值优化不是C ++ 11标准的一部分,因此 WHAT IF 由于某种原因,编译器决定在调用get()
时不执行返回值优化。在这种情况下,A
在get()
返回时会调用get()
的复制构造函数吗?
所以{{1}}的第一个实现不是更可靠吗?
答案 0 :(得分:2)
编译器应该使用移动构造函数,但我没有看到标准中的义务:
它总是在关于临时对象的部分中说“复制/移动构造函数”
标准ISO / IEC 14882:2011 C ++:
“
<强> 12.1 / 9 强>
复制构造函数(12.8)用于复制类类型的对象。移动构造函数(12.8)用于移动 类类型对象的内容。
<强> 12.8 / 32 强>
当满足或将满足复制操作的省略标准时,除了源的事实 object是一个函数参数,要复制的对象由 lvalue 指定,重载解析为 选择首先执行复制的构造函数,就好像该对象是由 rvalue 指定的一样。如果过载 分辨率失败,或者所选构造函数的第一个参数的类型不是 rvalue 引用 对象的类型(可能是cv-qualified),再次执行重载决策,将对象视为 左值。 [注意:无论是否复制,都必须执行此两阶段重载决策 发生。它确定在未执行elision时调用的构造函数以及所选的构造函数 即使通话被取消,也必须可以访问。 - 结束说明]
“
左值 = T &
rvalue = T &&
所以,它说,首先,编译器将查看是否找到了移动构造函数,然后,它将查找移动构造函数。
因此,如果您的编译器符合标准,它将调用移动构造函数。
我附加了有趣的内容:
“
的 12.8 / 31 强>
当满足某些条件时,允许实现省略类的复制/移动构造
对象,即使对象的复制/移动构造函数和/或析构函数有副作用
“
...所以即使这些构造函数/析构函数中存在副作用,也可以跳过它们