2013-12-14 21 views
4

我通過故意試圖破壞事情來測試我對左值和右值引用的理解。所以說有這個結構:存儲右值引用:應該工作嗎?

struct FooBar 
{ 
    FooBar(int&& number) : rNumber(number) 
    { 

    } 

    int& rNumber; 
}; 

我創建一個實例FooBar obj(5)。每次嘗試讀取引用變量都會返回正確的結果(5)。如果我使用const int&而不是int&&,則會發生同樣的情況。

我注意到用std::string代替int並且讀引用返回一個空字符串,所以我懷疑它給出了未定義的行爲。這是嗎?如果是這樣,爲什麼它使用整數?

更新:我創建的實例,並閱讀它是這樣的:

FooBar obj(5); 
//FooBar obj("Hello"); // For strings... 

std::cout << obj.rNumber << std::endl; 

更新2:如果你傳遞一個用戶定義類型,這樣它也適用:

struct GooBar 
{ 
public: 
    GooBar(int number) : itsNumber(number) 
    { 
     std::cout << "In constructor..." << std::endl; 
    } 

    GooBar(const GooBar& rhs) = delete; 
    GooBar(GooBar&& rhs) = delete; 

    ~GooBar() 
    { 
     std::cout << "In destructor..." << std::endl; 
    } 

    int itsNumber; 
}; 


struct FooBar 
{ 
    FooBar(GooBar&& number) : rNumber(number) 
    { 

    } 

    GooBar& rNumber; 
}; 

,然後創建一個實例,並閱讀它,像這樣:

FooBar obj(GooBar(5)); 

std::cout << obj.rNumber.itsNumber << std::endl; 

我覺得這很有趣,因爲它提供了以下的輸出:

In constructor... 
In destructor... 
5 
+1

這確實是未定義的行爲,您是否啓用了警告進行編譯? (例如,clang'-Weverything') –

+0

如果我啓用所有警告,我會得到~700個警告,所以如果有任何與未定義行爲有關的行爲,我不能立即指出。至少源於我的源文件的警告並不存在,但在庫文件中還有其他警告。我在MSVC btw。 –

+0

嗯,我很抱歉你選擇的編譯器:(順便說一下,它不適合你的用戶類型;你可以通過在'GooBar'析構函數中將'itsNumber'設置爲'0'來展示它。 –

回答

2

隨着文字的整數作爲實際參數,編譯器可以傳遞到靜態分配的實例的引用。

使用std::string形式參數和字符串文字作爲實際參數,實例在調用中創建,並在調用結束時銷燬。

在這兩種情況下,它都是未定義的行爲。


你怎麼稱呼這雖然目前還不清楚:你忘了包括關鍵信息(如問題是因爲在當時我在寫這一點)。

+0

剛剛添加。謝謝 –

+0

我想我明白了,但如果你能就我發佈的第二個更新給我你的想法,我會很感激。謝謝! –

+0

@ KristianD'Amato我認爲這是一個懸而未決的參考(Alf可以糾正我)。對象'rNumber'必然存在,直到FooBar的構造函數結束,然後poof,它消失了。正如我所說的,你必須調用'lvalue'上的'std :: move'來使它工作。 – 2013-12-14 18:18:32

相關問題