我从函数中返回非命名对象。为什么RVO还会继续?

时间:2014-12-11 13:40:50

标签: c++ c++11 rvo

对此: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?

2 个答案:

答案 0 :(得分:7)

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

当返回临时(通常使用临时来初始化相同类型的对象)以及返回局部变量时,允许复制省略。

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

答案 1 :(得分:3)

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

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