2

关于这一点:为什么 std::move 会阻止 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;
}

producerX 函数不返回命名值。它返回一个未命名的临时对象。然而,RVO 仍然启动,并且没有复制或移动构造。main 中的 x 对象是就地构造的。如果我这样写produceX:

X produceX()
{
    X localNamedObject;
    return localNamedObject;
}

它的行为方式相同(这是预期的)。但是为什么在前一种情况下允许 RVO 呢?

4

2 回答 2

7

该声明过于简化,尽管您从中得出的答案实际上确实回答了这个问题,并提供了标准中的相关文本。

当返回一个临时对象(作为使用临时对象初始化相同类型的对象的一般情况)以及返回一个局部变量时,允许复制省略。

在按值抛出和捕获异常时也允许这样做,但这超出了这个问题的范围。

于 2014-12-11T13:44:18.990 回答
3

RVO 代表“返回值优化”,指的是直接在返回值空间内构造返回表达式结果的技术。当返回表达式是一个右值时应用它。

NRVO 代表“命名返回值优化”,指的是构造最终将在返回值空间内直接返回的命名对象的技术。当返回表达式是左值时应用它。

于 2014-12-11T13:44:32.380 回答