2009-08-21 53 views
6
struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    return A::B::b; 
} 

上面的代碼編譯。但是,如果你按照Scott Myers的有效C++書(第14頁); 除宣言外,我們還需要一個定義。 任何人都可以解釋爲什麼這是一個例外?在結構/類中使用靜態const int

+1

代碼_does_包含'a'的定義。 – 2009-08-21 14:29:17

+2

不,它不包含定義。 – 2009-08-21 14:42:32

+1

@亨克。不是真的。嘗試將'a'或'b'的地址傳遞給函數,並查看編譯器生成的消息! – 2009-08-21 14:43:10

回答

18

C++編譯器允許靜態const整數(僅限整數)在聲明的位置指定其值。這是因爲變量本質上不是必需的,並且只存在於代碼中(通常編譯出來)。

其他變量類型(如靜態const char *)通常無法定義它們在哪裏聲明,並且需要單獨的定義。

想了解更多解釋,請認識到訪問全局變量通常需要在較低級別的代碼中進行地址引用。但是你的全局變量是一個整數,它的大小通常大約是一個地址的大小,編譯器意識到它永遠不會改變,所以爲什麼要添加指針抽象呢?

+0

+1,很好的答案。但是如果'const'整數呢?我們能在課堂上指定他們的價值嗎? – Alcott 2012-03-28 12:21:12

+0

不是「整數」,只是常量表達 – czxyl 2017-11-13 11:37:54

18

通過真正的迂迴規則,是的,你的代碼需要一個靜態整數的定義。但是通過實際的規則以及所有編譯器實現的內容,因爲這就是C++ 03的規則是如何實現的 - 不,您不需要定義。

這樣的靜態常量整數的規則旨在允許您省略定義,如果僅在立即讀取值的情況下使用整數,並且如果可以在常量表達式中使用靜態成員。

在你的return語句中,成員的值立即被讀取,所以你可以省略靜態常量整數成員的定義,如果這是它的唯一用處。但是,以下情況需要定義:

struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    int *p = &A::B::b; 
} 

此處未讀取任何值 - 但取而代之的是其地址。因此,C++ 03標準的目的是在一些實現文件中必須爲成員提供如下的定義。

const int A::B::b; 

注意,出現在C++ 03標準的實際規則說,其中一個常量表達式是需要的定義不僅當使用可變必需的。但是,如果嚴格適用,這條規則太嚴格了。它只允許你省略像數組維度這樣的情況的定義 - 但是在像return語句這樣的情況下需要定義。相應的缺陷報告是here

C++ 0x的措辭已經更新,包括缺陷報告的解決方案,並允許您的代碼寫入。

+0

這是否意味着Walt W在他說:「C++編譯器允許在它們聲明的位置定義靜態常量整數(和整數)時是錯誤的?我以爲他喜歡「靜態const int a = 5;」聲明既是聲明又是定義。如果我理解正確,它只是一個沒有任何定義的聲明,而A :: a只能用於非常特殊的情況。我對最後一句話很感興趣...... – neuro 2009-08-21 18:00:59

+0

是的,他也錯了。這只是一個聲明 - 這不是一個定義。如果在不立即讀取值的情況下引用它,則需要定義。你的評論似乎是正確的。 – 2009-08-21 18:55:08

+0

更好?我想這不是「定義」的技術用法 – 2009-08-21 21:07:04

0

在一般情況下,大多數(和最近的)C++編譯器允許靜態常量整型

你只是運氣好,也許不是。嘗試使用舊版本的編譯器,例如gcc 2.0,它會用嚴厲的錯誤信息強烈懲罰你。

1

但是,如果你嘗試沒有「界定」三元操作靜態consts,你在GCC 4倍得到一個鏈接錯誤:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795

所以,雖然像int k = A::CONSTVAL;結構是非法的現行標準,他們受到支持。但三元操作數不是。有些運營商比其他運營商更平等,如果你得到我的漂移:)

對於「寬鬆」的規則如此之多。如果你不想要驚喜,我建議你寫符合標準的代碼。