复制-删除返回的自动变量



我想知道是否在c++ 0x "12.8复制和移动类对象[class。当复制省略发生时,确切地说:

当满足某些条件时,允许实现省略类对象的复制/移动构造[…]。拷贝/移动的省略在以下情况下,允许进行称为复制省略的操作[…]:

  • 在具有类返回类型的函数的返回语句中,当表达式是一个非易失性自动对象的名称时[…]]与函数返回类型相同的cv-不限定类型,可以通过构造来省略复制/移动操作将自动对象直接转换为函数的返回值
  • […]
现在我想知道,这是否允许在下面的代码中避免复制
vector<string> gen(const char *fn) {
    if(fn == nullptr)  // this should prevent RVO
        return {"House", "Horse", "Hen"};
    vector<string> res;
    fillFromFile(res, fn);
    return res;  // copy elision possible?
}
int main() {
    vector<string> data = gen("users.dat");
}

或者这个规则不适合这个例子,我必须显式地写出来吗?

    return move(res);  // explicitly prevent copy

请注意,我的if的意图是消除明显的返回值优化 (RVO)。

还是我完全搞错了方向?有一个涉及returnmove的变化,可以使用右值引用,对吧?

是的,在这两种情况下都可以/允许复制省略。

在编译器术语中,这两种情况略有不同。return {"House", "Horse", "Hen"};构造了一个未命名的对象,所以常规的RVO开始了。

return res;稍微复杂一些,因为您返回的是之前已经构造好的命名对象。这种优化通常被称为NRVO(命名返回值优化),编译器实现它的情况略少。

MSVC总是实现RVO,并且在发布版本中执行NRVO。

我相信最近版本的GCC总是同时执行RVO和NRVO。

顺便说一下,我真的不明白为什么你的"如果"会对RVO产生影响。

是的,在这种情况下,编译器有特定的指令将res视为右值,并且res将被移到data中。当然,编译器可以很容易地在这里应用RVO/NRVO,因为它可以静态地确定您永远不会使用nullptr调用该函数,此外,该函数可以进行简单的转换,以便即使无法证明也可以应用RVO/NRVO,最后,这甚至不妨碍RVO/NRVO,因为结果仍然可以在。

中构造。

最新更新