2013-04-16 151 views
4

當我在VS2010中運行此代碼時,不應用NRVO。爲什麼NRVO不適用於此?

#include <stdio.h> 

class A 
{ 
    public: 

    A() { printf("I am in constructor\n"); } 
    A(const A& a) { printf("I am in copy constructor\n"); } 
    ~A() { printf("I am in destructor\n"); } 
    int i;  
}; 

A f(int j) 
{ 
    A a; 
    if (j) return a; 
    a.i = j; 
    return a; 
} 

int main() 
{ 
    A a; 
    a = f(5); 
} 

編輯:這與析構函數有關。當我發表評論時,使用NRVO。但爲什麼呢?

+3

您使用的是哪種優化級別?還要注意的是,如果有一個單一的回報,在這種情況下是微不足道的,那麼應用NRVO就簡單多了,用'if'代替:if(!j)ai = j;'那麼它將有更高的應用機會。 –

+0

看這裏,http://msdn.microsoft.com/en-us/library/ms364057%28v=vs.80%29.aspx有NRVO的限制。你確定,你有優化啓用? – kassak

+0

@DavidRodríguez-dribeas我嘗試過所有的優化選項,結果是一樣的。 – Belloc

回答

3

爲什麼NRVO不適用於此?

如果你想知道VC10如何通過算法來決定是否執行NRVO,那麼誰可以回答這個問題的唯一的人確實是那些誰知道VC10內部工作你這個單純的好奇心, - 那些誰寫的。

據我所知,根據C++ 11標準,編譯器允許在這種情況下執行NRVO,而不是這樣做只是編譯器的決定 - 不是由於任何有效性約束。每個段落12.8/31:

[...]複製/移動操作的此省音,稱爲複製省略,允許在下列情況下(其 可以被組合,以消除多個副本):

- 在帶有類返回類型的函數的返回語句中,當表達式是具有相同cv不合格 類型的非易失性自動對象(函數或catch-clause參數除外)的名稱 作爲函數返回類型,複製/移動操作可以通過構造 自動對象di rectly到函數的返回值

[...]

但是,如果你與期望,你應該能夠你的編譯器執行NRVO問,那麼答案是「 你不能「。

完全由編譯器決定是否應用NRVO。你不能指望它,你不能指望它而不是正在執行。據我所知,這是所謂的「as-if」規則的唯一例外。

這就是說,獲得NRVO的機會會隨着你的增加而增加的優化水平。

+0

我只是想知道爲什麼它不適用於此。 – Belloc

+0

@ user1042389:好的。在這種情況下,很難得到答案。我可以告訴的是,C++標準確實允許NRVO,所以答案不是「因爲它是不允許的」。 –

0

我不知道你在你的環境中看到,但這個工程在GCC預期(如see here):

正常:

I am in constructor 
I am in constructor 
I am in destructor 
I am in destructor 

隨着-fno-elide-constructors

I am in constructor 
I am in constructor 
I am in copy constructor 
I am in destructor 
I am in destructor 
I am in destructor 
+0

我在發佈版本中獲得第二個輸出,即在VS2010中啓用優化。 – Belloc

相關問題