簡體   English   中英

為什么不執行“部分RVO”?

[英]Why is “partial RVO” not performed?

請看一下這個愚蠢的函數,它應該只說明問題並簡化實際代碼:

struct A;

A create(bool first){
        A f(21), s(42);
        if(first)
           return f;
        else
           return s;
}

我理解,因為在編譯期間不清楚返回哪個對象,我們不能指望總是執行返回值優化(RVO)。

然而,人們可能期望在50%的情況下執行RVO(假設由於缺乏進一步的信息而實現true / false均勻分布):只需決定RVO( first==truefirst==false )應該是哪種情況執行並將其應用於此參數值,接受在另一種情況下必須調用復制構造函數。

然而,對於我可以得到的所有編譯器來說,這個“部分RVO”並非如此(請參閱gccclangMSVC ) - 在這兩種情況下(即first==truefirst==false )復制構造函數是使用而不是省略。

是否存在導致上述情況下“部分RVO”無效的情況,或者這是否是所有編譯器錯過優化的不太可能的情況?


完整計划:

#include <iostream>

struct A{
    int val;
    A(int val_):val(val_){}
    A(const A&o):val(o.val){
        std::cout<<"copying: "<<val<<"\n";
    }
};

A create(bool first){
        A f(21), s(42);
        if(first)
           return f;
        else
           return s;
}

int main(){
    std::cout<<"With true: ";
    create(true);
    std::cout<<"With false: ";
    create(false);
}

讓我們考慮如果對f RVO會發生什么,這意味着它是直接在返回值中構造的。 如果first==true並返回f ,那么很棒,不需要復制。 但是如果first==false則會返回s ,所以程序會在f的析構f運行之前將構造s復制到f的頂部。 然后, f的析構f將運行,現在返回值是一個已被銷毀的無效對象!

如果對s了RVO,則應用相同的參數,但現在問題發生在first==true

無論您選擇哪一個,在50%的情況下都可以避免復制,並在其他50%的情況下獲得未定義的行為! 這不是一個理想的優化!

為了使這項工作,必須改變局部變量的破壞順序,以便s復制到該存儲器位置之前銷毀f (反之亦然),這是一個非常危險的事情。 破壞的順序是C ++的一個基本屬性,不應該被擺弄,或者你將破壞RAII,誰知道有多少其他假設。

除了閱讀Jonathan Wakely的答案之外,我對此的看法是,總是可以為返回的對象定義移動構造函數。 如果RVO由於某種原因無法應用,那么這將比復制構造函數更受青睞,並且在我看來這是一個很好的解決方案。

std::vector類的東西定義了這樣的構造函數,所以你可以免費獲得它。

暫無
暫無

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

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