本地堆栈变量成员的返回值优化

alf*_*lfC 3 c++ reference member-variables return-value-optimization

我有一段通用代码,在实例化时,归结为:

struct A{...};

A f1(){
    A ret;
    std::pair<A&, int> p(ret, 1);
    p = g(); // g returns a pair<A, int>, but I am not interested in g
    return ret; // RVO :)
};
Run Code Online (Sandbox Code Playgroud)

据我了解,这将适用于RVO.

问题是,这个其他代码是否会返回ARVO 类型的对象?

A f2(){
    std::pair<A, int> p;
    p = g();
    return p.first; // RVO ?
};
Run Code Online (Sandbox Code Playgroud)

我理解,由于返回对象被遮挡,它不会做RVO或者编译器可能无法选择"优化".但我没有看到为什么它不可能的根本原因,换句话说,我认为一致性,它应该做RVO(我想要).

我问的原因是因为我认为f2代码比较优雅f1.

这最后一个版本应该做RVO吗?如果是这样,它是编译器依赖的吗?


我用gcc 8.1原油测试给出了RVO不工作f2f3以下:

struct A{
    double something;
    A() = default;
    A(A const& other) : something(other.something){std::cerr << "cc" << '\n';}
    A(A&& other) : something(other.something){std::cerr << "mc" << '\n';}
};

A f1(){
    A ret;
    std::pair<A&, int> p(ret, 1);
    p.first.something = 5.;
    return ret; // RVO :)
};

A f2(){
    std::pair<A, int> p;//(ret, 1);
    p.first.something = 5.;
    return p.first; // no RVO :(
};

A f3(){
    std::pair<A, int> p;//(ret, 1);
    p.first.something = 5.;
    return std::move(p).first; // no RVO :(
};


int main(){
    A a1 = f1(); // prints nothing, RVO
    A a2 = f2(); // prints "cc"; no RVO! Why?
    A a3 = f3(); // prints "mc" (no much gain in this case); still no RVO!
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*nck 5

要使RVO工作,需要在调用者期望找到它的存储中实例化返回值.也许这是一个寄存器,其名称由调用约定指定,或者它可能在堆栈中.

std::pair<A, int> 基本上是:

struct foo {
    A first;
    int second;
};
Run Code Online (Sandbox Code Playgroud)

现在,如果返回值需要存储在某个特定地点sizeof(A),但对具有更大的尺寸,这对不可能被存储在那里.RVO仍然可以工作的唯一方法是,如果被调用者知道sizeof(int)在执行函数时允许返回值后面的字节被破坏.但在这种情况下,语言可能不应该要求RVO,因为它可能无法在每个调用约定中实现.