8

該問題與隨後提出的問題密切相關here.爲什麼不Visual Studio 2010調試器請參閱靜態常量類成員?

Stroustrup描述了定義類內常量的方法here

當我按照Stroustrup的方法,我看到了預期的結果。但是,在Visual Studio 2010中,調試器無法解析類的範圍內的類成員。 這裏是我的意思是:

#include <iostream> 

class Foo { 
    public: 
    static const int A = 50; 
    char arr[A]; 
    void showA(); 
}; 

void Foo::showA() { 
    std::cout << "showA = " << A << "\n"; 
} 

int main() { 
    Foo f; 
    f.showA(); 
} 

當調試器是在昭和()「監視」窗口報告:

Error: Symbol "Foo::A" not found 

我想強調的是程序沒有像預期的那樣,即輸出:

showA = 50 

和程序返回0

人否則用Visual Studio 2010重現這一點?這是調試器中的錯誤嗎?

+1

請注意,您缺少「A」靜態數據成員的定義 – 2013-05-03 19:01:38

+0

它是內聯的,對於OP的點 – 2013-05-03 19:04:27

+0

是否啓用了優化?該類是否在命名空間內? – 2013-05-03 19:07:05

回答

2

的Visual C++錯誤地提供了基於類內的聲明a weak definition (evidence provided in this answer),儘管在標準清晰的語言:

在其類定義的靜態數據成員的聲明是不是定義,並且可以是除cv-qualified void以外的不完整類型。靜態數據成員的定義應出現在包含成員的類定義的命名空間範圍內。在名稱空間範圍的定義中,靜態數據成員的名稱應使用::運算符通過其類名進行限定。

根據標準的另一個規則,如果成員是不需要定義不ODR使用的

但是,是否存在由Visual C++錯誤提供的顯式定義或弱定義沒有任何區別。如果成員不是odr-used,鏈接器將不會看到任何對它的引用,並將刪除它,從而使調試器對它是否存在感到困惑。使用Microsoft鏈接器,您可以使用/OPT:NOREF禁止此優化。但是,最終你不想在生產代碼中做這件事,因爲你會在應用程序中留下標準庫中的各種退化的東西。但是在調試期間臨時使用這是一個合理的設置。

3

這不是一個錯誤。編譯器可以(並且幾乎總是)會優化靜態常量基本類型。編譯器不是爲A分配存儲空間,而是將A的值內聯到編譯的指令中。

因爲A沒有存儲在任何地方,所以它沒有地址,所以調試器無法查看它。

+1

這裏*有*錯誤,儘管內聯值不是它。無論代碼是否包含一個(即錯誤),編譯器實際上都會發出一個定義,即使每次使用都是內聯的。然後*鏈接器*刪除定義,因爲沒有任何東西取決於它的存在。 – 2013-05-06 19:51:39

7

您可在全球命名空間範圍添加定義您的靜態數據成員:

const int Foo::A; 

添加靜態數據成員的定義,這是沒有必要的,但允許,似乎解決您的問題。

我在VS2010的調試版上測試了這個,當定義出現時,調試窗口中的值正確顯示(當定義丟失時報告錯誤消息,與您提到的一致) 。

+0

謝謝你引用標準。 [111]回覆[這個問題](http://stackoverflow.com/questions/1563897/c-static-constant-string-class-member)表示「初始化[ations]在類定義[s] [僅]允許使用整型和枚舉類型「。而且,Stroustrup的文章似乎暗示只有在您需要訪問該成員的地址時才需要全局定義。添加VS10和GCC/Cygwin代碼「按預期工作」的事實,我敢打賭,很多人都沒有意識到仍然需要全局定義。 +1 – user2141130 2013-05-03 20:50:50

+1

@ user2141130:很高興幫助,確實還不明顯,仍然需要一個定義 – 2013-05-03 21:26:26

+0

我已經添加了您可能會喜歡看的更新。 – user2141130 2013-05-04 00:15:30

相關問題