2011-05-16 55 views
4

我是C++的新手。請考慮下面的代碼:在C++中創建沒有RVO的對象和副本ctors

class foo 
{ 
int f; 

public: 
    foo(int f1=0) : f(f1) { 
    cout<<"In conversion ctor\n"; 
} 

foo(const foo & rhs) : f(rhs.f) 
{ 
    cout<<" In copy ctor\n"; 
} 

foo& operator=(const foo & that) 
{ 
    f=that.f; 
    cout<<"In = optor\n"; 
    return *this; 
} 

}; 

foo rbv() 
    { 
    foo obj(9); 
    return obj;      //named return by value [def. 1] 
    } 

    foo caller() 
    { 
     return rbv();    // return by value [def. 2] 
    } 

int main(void) 
{ 
    foo box=caller(); 
    return 0; 
} 
  1. 是RBV和NRBV正確的定義如 評論指出?
  2. 雖然在RVO期間沒有調用 ,但它是否需要定義可訪問的副本?
  3. 沒有視網膜靜脈阻塞,在代碼塊

    foo rbv() 
        { 
        foo obj(9); 
        return obj; 
        } 
    
        foo ret= rbv(); 
    

是在創造 'RET'

(1)臨時(比如obj_temp)創建使用拷貝構造函數的正確執行以下步驟從obj, 堆棧對象'obj'被銷燬,

(2)ret是從obj_temp構造的複製,obj_temp後來銷燬;這意味着有三個對象'obj','obj_temp'和'ret'以及兩個拷貝參與者。

+1

你運行它時看到了什麼文字?它確認你的猜測嗎? – dlev 2011-05-16 20:09:49

+2

如果您不熟悉C++,那麼您應該關注的東西比RVO更多。大多數(可能90%以上)的課程都不應該是可複製的。 – 2011-05-16 20:18:22

+0

def。 1是NRVO,def。 2是RVO,Q中缺少'O'和一些錯別字。 @dlev沒有優化,只考慮NRVO和調用rbv()而不是調用者(),1個轉換器,調用2個副本。這證實了我的猜測。只有優化轉換ctor被調用。 – Burt 2011-05-16 23:03:39

回答

0
  1. 看起來是對我的。
  2. 如果您要複製對象,則必須定義可訪問的複製構造函數。即使副本可以被優化掉。
  3. 這聽起來是對的,儘管精確的排序可能是實現定義的。您必須
5

RBV和NRBV的定義是否正確,如註釋中所示?

他們是RVO和NRVO(返回值優化和命名返回值優化)

是否必須有定義,雖然它不RVO中調用的可訪問副本構造函數?

這是強制性的,編譯器必須驗證構造函數是否可訪問,如果它們不是,編譯器必須觸發錯誤並且無法編譯。

沒有視網膜靜脈阻塞,在代碼塊

foo rbv() { 
    foo obj(9); 
    return obj; 
} 
foo ret = rbv(); 

的代碼,因爲它代表需要以下操作:構造服用intfoo創建obj。將退貨聲明中的施工複製到臨時退貨$tmp1,在臨時地點複製施工地點ret。現在,編譯器可以通過在ret的頂部放置返回值(根據調用約定)來取消兩個副本,所以$tmp1ret是相同的存儲器位置,並且通過在同一存儲器位置上構造obj,所以在結束所有三個對象可以是單個對象並且不需要執行副本。