2013-06-27 20 views
1

可以修改我有一些像這樣的代碼,其中VEC某種載體類:避免構造一個新的對象,如果它是一個參數,而不是

Vec Vec::choose(const Vec& ifPositive, const Vec& ifNegative) const { 
    Vec out(mSize); 
    for(int index = 0; index < mSize; ++index) { 
     if(mData[i] > 0) 
      out[i] = ifPositive[i]; 
     else 
      out[i] = ifNegative[i]; 
    } 
    return out; 
} 

下面這段代碼工作正常在一般情況下,但如果函數的左手邊是一個參數,也有一些不必要的constuctor /析構函數調用:

curVal = trigger.choose(posVal, curVal); // construct is called in choose, then old curVal is destroyed 

是有一些方法來提高/避免這種情況,如果編譯器看到喜歡當左函數的手邊是其中一個參數,它會運行不同的代碼?

編輯: 下面是一些示例代碼:http://ideone.com/nPUK3h

我想知道,如果它能夠ommit最後(4)建設。 我將在稍後在家中進行一些更復雜的優化來編譯。

EDIT2: 我能避免額外的結構,如果我介紹以下附加功能:

Vec& Vec::setNegative(Vec& target, const Vec& ifNegative) const { 
    for(int index = 0; index < mSize; ++index) { 
     if(mData[index] <= 0) 
      target[index] = ifNegative[index]; 
    } 
    return target; 
} 

因此,如果選擇功能的LHS是相同的作爲第一個參數,這產生相同的輸出,然而,如果lhs是另一個向量,我希望得到一個新的向量。

有什麼方法可以通過一些模板魔法或編譯器技術在兩者之間進行選擇?

+2

使用支持RVO的理智編譯器。 – PlasmaHH

+0

它實際上是否構成多餘的副本?根據您的編譯器,優化級別和調用代碼的結構,您可能會發現它會忽略您擔心的部分或全部冗餘。 –

+0

我沒有看到你在函數中的任何地方使用'ifNegative'。錯字? – jrok

回答

1

IIRC,RVO允許編譯器在接收對象的位置構造返回值,但在這種情況下,該對象的引用正在被調用中使用,即返回值是在參數之前構造的用來。

所以我可以看到這將如何擊敗RVO。我不明白爲什麼它會打敗移動。

+0

如果添加一個寫入cout的移動構造函數,您可以看到被調用。 – doctorlove

+0

如果我將最後一行更改爲Vec valC =觸發器。選擇(valA,valB);我仍然得到了四個名爲 – doctorlove

+0

的構造函數,我明白了你的觀點,在函數中確實無法避免附加的構造函數 - 但它可以通過具有類似接口的另一個函數來消除。但是,問題將在於兩個函數如何在兩個函數之間進行選擇,具體取決於參數1是否與函數的左側相同。 – Michael

0

在移動語義中使用C++ 11編譯器。返回的Vec對象是無名稱的,可以從中移出。

請記住,寫入的代碼是強烈異常安全的。如果任何分配失敗,curVal未觸及。任何通過即時修改curVal而工作的「優化」很可能會打破這一點。

+0

我在VS2012上得到了相同的行爲,它支持移動語義。構造函數是否停止了RVO?我認爲RVO在C++ 11中仍然是可能的。 – doctorlove

+0

我也在gcc 4.6.3上得到了四個構造。如果我添加一個移動構造函數,我會得到四個,然後移動。 – doctorlove

+0

四?無論如何,這是很多。 – MSalters

相關問題