簡體   English   中英

本地堆棧變量成員的返回值優化

[英]Return value optimization of a member of a local stack variable

我有一段通用代碼,在實例化時,歸結為:

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 :)
};

據我了解,這將適用於RVO。

問題是,這個其他代碼是否會返回帶有RVO的A類對象?

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

我理解,由於返回對象被遮擋,它不會做RVO或者編譯器可能無法選擇“優化”。 但我沒有看到為什么它不可能的根本原因,換句話說,我認為一致性,它應該做RVO(我想要)。

我問的原因是因為我覺得f2f1更優雅。

這最后一個版本應該做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!
}

要使RVO工作,需要在調用者期望找到它的存儲中實例化返回值。 也許這是一個寄存器,其名稱由調用約定指定,或者它可能在堆棧中。

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

struct foo {
    A first;
    int second;
};

現在,如果返回值需要存儲在sizeof(A)的特定位置,但該對具有更大的大小,則該對不可能存儲在那里。 RVO仍然可以工作的唯一方法是,如果被調用者知道在執行函數時允許返回值后面的sizeof(int)字節被破壞。 但在這種情況下,語言可能不應該要求RVO,因為它可能無法在每個調用約定中實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM