返回std :: move的局部变量

时间:2013-08-14 09:30:49

标签: c++ c++11 move-semantics return-value-optimization

让我们有一个带有移动构造函数的类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()时不执行返回值优化。在这种情况下,Aget()返回时会调用get()的复制构造函数吗?

所以{{1}}的第一个实现不是更可靠吗?

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 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使对象的复制/移动构造函数和/或析构函数有副作用 “

...所以即使这些构造函数/析构函数中存在副作用,也可以跳过它们