2011-12-08 36 views
16

在C++中,函數中的自動變量被銷燬之前,是否會保證創建一個返回值?通知籃::獲得:自動變量銷燬之前或之後創建的C++返回值?

class Basket 
{ 
public: 
    // Gift is a struct containing safely copyable things like int or string 
    Gift gift; 
    // Used to protect access and changes to gift 
    Mutex mutex; 

    // Copy gift into present, while locked to be thread safe 
    void put (const Gift & gift) 
    { 
    Lock lock(mutex); // Constructor locks, destructor unlocks mutex 
    this->gift = gift; // Gift assignment operator 
    } 

    // Return a memberwise-copy of gift, tries to be thread safe (but is it?) 
    Gift get() 
    { 
    Lock lock(mutex); // Constructor locks, destructor unlocks mutex 
    return gift;  // Gift copy constructor 
    } 
}; 

我需要籃::去鎖對象銷燬前履行禮品拷貝構造函數(的臨時對象返回)。否則,返回的禮物對象可能會被同時放置的電話損壞。

我的測試顯示禮物副本確實是在鎖定銷燬之前創建的,但是,它有保證嗎?如果沒有,我需要在函數內創建第二個臨時對象,如:

Gift get() 
    { 
    Gift result; 
    { 
     Lock lock(mutex); 
     result = gift; 
    } 
    return result; 
    } 

回答

12

是,自動變量將保持在範圍內迴歸完成後,直到。如果您使用的編譯器優化return,這是尤其如此:

Gift get() 
{ 
    Lock lock(mutex); 
    return gift; 
} 

Gift g = basket.get(); 

這將是equivilent這個順序:

Gift g; 
Lock lock(mutex); 
g = Gift(gift); 
~lock(); 

可以被優化以表現得更像這樣:

void get(Gift &ret) 
{ 
    Lock lock(mutex); 
    ret = gift; 
} 

Gift g; 
basket.get(g); 

這將是equivilent這個順序:

Gift g; 
Lock lock(mutex); 
g = gift; 
~lock(); 

換句話說,在return期間可以刪除臨時文件。

3

這是有保證的。在銷燬之前複製返回值(如有必要)。這是一個類似的問題/答案,可以很好地描述序列。

Scope and return values in C++

+1

在C++標準中沒有寄存器這樣的東西。 (好吧,有'register'關鍵字,但很久以前它就失去了它的含義。)另外,大多數對象都不適合單個寄存器。 – fredoverflow

+0

如果返回一個本地對象,那麼當然,它必須在它被銷燬之前被複制。但是,這是另一回事。我有一個返回類的數據成員,所以複製發生時的語義似乎不同。 – maxpolk

+0

@maxpolk您正在通過值返回成員。除非編譯器可以像Remy所顯示的那樣將其優化爲參考任務,否則將會有一個副本。如果你正在返回一個引用或指針,那麼鎖之後仍然會被銷燬。 – AJG85

相關問題