对此:Why does std::move prevent RVO?有人写道:“因此,在返回语句中,只有当表达式本地变量的名称时才会出现复制省略”
但是我在GCC做了一点测试:
class X
{
public:
X()
{
cout << "def" << endl;
}
X(const X& x)
{
cout << "copy" << endl;
}
X(X&& x)
{
cout << "move" << endl;
}
};
X produceX()
{
return X();
}
int main()
{
X x{produceX()};
return 0;
}
produceX函数不返回命名值。它返回一个未命名的临时对象。然而,RVO仍然踢,并没有复制或移动建设。 main中的x对象就地构造。如果我写这样的produceX:
X produceX()
{
X localNamedObject;
return localNamedObject;
}
它的行为方式相同(预期)。但为什么在前一种情况下允许使用RVO?
答案 0 :(得分:7)
该陈述过于简化,尽管您从中得到的答案确实回答了这个问题,并提供了标准中的相关文本。
当返回临时(通常使用临时来初始化相同类型的对象)以及返回局部变量时,允许复制省略。
在按价值投掷和捕捉异常时也允许这样做,但这超出了这个问题的范围。
答案 1 :(得分:3)
RVO代表“返回值优化”,指的是直接在返回值空间内构造返回表达式结果的技术。当返回表达式为右值时应用它。
NRVO代表“命名返回值优化”,指的是构造最终将在返回值空间内直接返回的命名对象的技术。当返回表达式为左值时应用它。