2014-04-14 39 views
26

http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/它提到了「最重要的const」,C++故意指定將臨時對象綁定到堆棧上的const引用將臨時的生命週期延長到引用本身的生命週期。我想知道爲什麼C++只允許當引用是const時延長對象的生命週期而不是當它不是時?該功能背後的理性是什麼?爲什麼它必須是const?爲什麼「最重要的const」必須是const?

+1

我希望在這裏引用標準,因爲我從來沒有能夠完全說服自己,它*確實需要'const'。 (在N3936中查看12.2 p4和5)。 – BoBTFish

+0

以便編譯器不必在對象超出範圍之前驗證沒有路徑修改臨時文件。 –

+4

@BoBTFish:您正在查看綁定到引用的臨時對象的生命週期。有關如何綁定它們的規則,請參閱[dcl.init.ref](C++ 11中的8.5.3)。特別是,p5的最後一個項目符號:「該引用應該是對非易失性** const **類型[或]右值引用的左值引用。」 –

回答

14

考慮以下情況:如果這被允許

int& x = 5; 
x = 6; 

應該發生什麼?相比之下,如果你做

const int& x = 5; 

將沒有合法的方式來修改x

+0

應該創建一個值爲5的隱藏本地變量。沒有技術原因不允許。 –

+1

@NeilKirk然而,這並不是你期待的'int&',它只是編譯器設計者的一個負擔,並且與int x = 5沒有區別。 –

+2

@tohecz但這是如何使用來自正常函數的返回值實現const ref綁定。所有功能對於編譯器設計人員來說都是「負擔」,這並不是它成爲功能的原因! – dan

24

下面是一個例子:

void square(int &x) 
{ 
    x = x * x; 
} 

int main() 
{ 
    float f = 3.0f; 

    square(f); 

    std::cout << f << '\n'; 
} 

如果臨時變量可以結合非const左值引用,上述將愉快地編譯,但產生相當令人吃驚的結果(的3而不是9輸出)。

+0

有趣的是,我沒有想到這一點。 –

+2

爲什麼會輸出3? – 0x499602D2

+0

我認爲這是通常的解釋。如果在複製樣式初始化中允許它,但在參數初始化中不允許呢?已經有顯式轉換和隱式轉換。 –

1

請注意,const引用可以綁定到甚至沒有正常地址的對象。 A const int &函數參數可以採用由文字常量表達式42組成的參數。我們不能接受42的地址,所以我們不能將它傳遞給需要const int *的函數。

爲了能夠綁定到像這樣的右值,const引用特別「有福」。

當然,對於像2 + 2這樣的傳統rvalues來說,生存期並不是問題。這是類類型的右值的一個問題。

如果參考的結合被允許一些對象,不像42,不具有普遍的壽命,即壽命具有被擴展,使得參考在其整個範圍清醒。

這不是說const會導致生命期延長,而是不允許非const引用。如果允許的話,還需要終生延期;在允許某些參考資料在其範圍的某些部分變壞方面沒有意義。這種行爲破壞了參考比指針更安全的概念。

相關問題