2013-11-01 36 views
3

我遇到了一個奇怪的問題。 考慮這個例子:static const int as map subscript

class Foo 
{ 
    static const int Bar = 5; 

public: 
    Foo() 
    { 
    _map[Bar] = "some characters"; 
    } 

    ~Foo() {} 

private: 
    std::map<int, std::string> _map; 
}; 

int main() 
{ 
    Foo a; 

    return (0); 
} 

我得到這個錯誤(使用g ++ 4.7.2編譯):

/tmp/ccLy806T.o: In function `Foo::Foo()': 
Main.cpp:(.text._ZN3FooC2Ev[_ZN3FooC5Ev]+0x1e): undefined reference to `Foo::Bar' 

現在,如果我做的static_cast在酒吧,它的工作原理:

Foo() 
{ 
    int i = Bar; //works 
    _map[static_cast<int>(Bar)] = "some characters"; //works 
} 

只有在構造函數中使用Bar作爲地圖下標時纔會出現此錯誤。在Foo類的其他函數中寫入_map[Bar] = "some characters";不會產生任何錯誤。

這對我來說真的很奇怪,但我希望這裏的某個人有一個答案。

那麼,我做錯了什麼?

+0

寫const int的美孚::酒吧= 5;之前你的主,但不在課堂上;) –

+0

類似地,'_map [+ Bar]'工作。一元'+'調用左值到右值的轉換(以及整數提升)。這會創建一個臨時的,可以在不使用ord的情況下使用Bar。 – dyp

+0

「只有在構造函數中使用Bar作爲地圖下標時纔會出現此錯誤。」 [不適用於所有編譯器](http://coliru.stacked-crooked.com/a/0e045e49b06f7a44)。請注意,標準(ODR)中的此規則如果違反,則不需要任何診斷。 – dyp

回答

4

這是因爲map::operator[]把它的關鍵作爲int const&。它需要你傳遞給它的東西的地址。當你這樣做:

_map[static_cast<int>(Bar)] 

你正在創建一個臨時的,並傳遞到該臨時地址,這很好。但是當你在做:

_map[Bar] 

Bar實際上沒有內存存儲。你需要通過向它提供:

class Foo { 
    .... 
}; 

const int Foo::Bar; 
+1

根據該標準,'Foo :: Bar'在'static_cast (Bar)'中不是* odr-used *,因爲Bar可以出現在一個常量表達式中,並且有一個左值到右值的轉換應用於'static_cast'。然而,'Bar'直接綁定到'const int&',因此沒有應用左值到右值的轉換 - 這是一個odr-use,它需要爲Bar定義。 – dyp

+0

@DyP感謝您的精心製作!我不知道那一點。 – Barry

0

您需要添加以下在頂層爲Foo::Bar分配存儲:

const int Foo::Bar;