2011-04-01 81 views
14

我通過鏈接錯誤使用下面的代碼時,百思不得其解(未定義參考):「靜態const int的」鏈接會導致錯誤

// static_const.cpp -- complete code 
#include <vector> 

struct Elem { 
    static const int value = 0; 
}; 

int main(int argc, char *argv[]) { 
    std::vector<Elem> v(1); 
    std::vector<Elem>::iterator it; 

    it = v.begin(); 
    return it->value; 
} 

然而,這種連接失敗時 - 不知它需要有一個符號爲靜態常量「值」。

$ g++ static_const.cpp 
/tmp/ccZTyfe7.o: In function `main': 
static_const.cpp:(.text+0x8e): undefined reference to `Elem::value' 
collect2: ld returned 1 exit status 

順便說一句,這個編譯好-O1或更好;但對於更復雜的情況仍然失敗。我使用的是gcc 4.4.4版本20100726(Red Hat 4.4.4-13)。

任何想法可能是我的代碼有問題嗎?

+1

[結構/類中的奇怪的未定義的靜態常量符號]重複(http://stackoverflow.com/questions/4891067/weird-undefined-symbols-of-static-constants-inside-a-struct-類) – karlphillip 2011-04-01 01:22:52

+0

感謝您的有用鏈接!它還顯示了一個替代解決方案,'struct Elem {enum {value = 0}; '',這看起來很有吸引力。 – hrr 2011-04-01 01:45:28

+0

[C++ - 在類定義中定義靜態常量整型成員]的可能重複(http://stackoverflow.com/questions/3025997/c-defining-static-const-integer-members-in-class-definition) – ks1322 2014-03-11 08:52:42

回答

8

如果你想初始化它結構裏面,你可以做到這一點:

struct Elem { 
    static const int value = 0; 
}; 

const int Elem::value; 
+0

這是涼!有用。如果可以(在該點知道該值)不在結構(類)中初始化它是沒有意義的,否則所有可能的優化都將丟失。 (即直接傳遞0,而不是從某個內存地址加載0)。 – 2012-04-29 07:04:26

+0

如果這真的是const,那麼可以使用「enum hack」的替代方法,參見:http://stackoverflow.com/questions/4891067/weird-undefined -symbols-of-static-constants-inside-a-struct-class這裏還描述了這些問題:在C++ 11枚舉之前沒有象「int」那樣的體面的「類型」,所以std :: min,std :: make_pair等等將不會猜測他們的模板參數... – 2014-03-04 15:25:44

5

試着寫它作爲

struct Elem { 
    static const int value; 
}; 

const int Elem::value = 0; 

etc 

+0

這將不幸地不工作,當值是switch語句中的標籤。 – Petr 2016-06-08 14:31:50

+0

@Petr對不起,不知道在那裏告訴你什麼。我在幾年內沒有使用過C++,所以我不知道這是'static const'特有的還是什麼。 – jonsca 2016-06-08 23:14:57

+1

我應該讓自己更清楚。我試圖指出任何人讀你的答案,即 - 雖然完全正確 - 有些情況下,這將無法正常工作。例如,如果你想在開關中使用'value'作爲標籤,就像'switch(x){case value:break; }' – Petr 2016-06-09 11:18:52

2

static通常認爲類成員在類的外部(在內部聲明,在外部定義)在一個編譯單元中定義。

我不記得如何與const靜態集成成員的內聯初始化進行交互。

+1

請參閱http://stackoverflow.com/questions/1312241/using-a-static-const-int-in-a-struct-class/1312267#1312267 – 2011-04-01 01:17:04

+1

沒有特殊規則的情況下,聲明有一個初始化器---根據標準,聲明的對象必須在可能被使用的地方定義。實際上,大多數編譯器在這方面都存在缺陷,並且如果定義丟失,只會在某些用途中產生錯誤,而不會爲其他用途產生錯誤。 (哪些用法從不指定,通常取決於優化級別。) – 2011-04-01 10:25:06

1

爲什麼不這樣做呢?

return Elem::value; 

但是答案是您在聲明中分配一個值。這應該適用於基本類型,如int,並且只適用於複雜類型(即類,如果您有字符串而不是int)。我在實踐中發現的是,這是根據您使用的編譯器的版本而定。而且,正如你發現的那樣,哪個優化級別。

+0

雖然這並不能解決初始化問題。另外,命中或失敗通常意味着未定義的行爲。 – jonsca 2011-04-01 01:21:32

+4

這只是避免他問的問題。 – 2011-04-01 01:22:42

+0

其實我回答了。我說他正在做的事情應該起作用(即沒有錯),但實際上並不總是奏效。他似乎找到了其中一個「不起作用」的案件。 – 2011-04-01 01:24:21

2

另請參閱this post:本質上,問題在於編譯器最終會將代碼擴展爲獲取Elem :: value的地址。