2009-10-26 72 views
1

我使用下面的代碼獲得以下錯誤。在全局級別實例化(C++)

expected constructor, destructor, or type conversion before '=' token 

-

#include <string> 
#include <map> 

class Foo { 

}; 

std::map<std::string, Foo> map; 
map["bar"] = Foo(); 

int main() 
{ 

    return 0; 
} 
+2

你的問題不是「在全球範圍內實例化」,而是「試圖在全球範圍內執行一個語句」。你不能這麼做,對不起。 – 2009-10-26 23:17:02

回答

13
map["bar"] = Foo(); // This line is a statement not a declaration. 
        // You have to put it in main, or any execution context 

,直到的C++ 0x成爲主流,我建議使用boost。填充map變得小菜一碟。這裏是一個例子:

std::map<std::string, Foo> mymap; 
... 
int main() 
{ 
    insert(mymap) 
    ("First", Foo(...)) 
    ("Second", Foo(...)) 
    ("Third", Foo(...)); 
    ... 
} 
1

它看起來像你想要的是一個靜態的初始化。我建議你閱讀this。它說明了靜態初始化器的使用,以及它們的主要陷阱,靜態初始化順序。

+2

爲什麼downvotes?至少留下建設性的意見。 – 2009-10-26 23:40:29

+0

我沒有讓你失望,但我想我明白你爲什麼不是一個好的答案。它沒有解決這個問題。靜態初始化和有序的危險可能是他的問題的答案的一部分,但你沒有包括這一點。 – 2009-10-27 00:56:16

+0

在C++中沒有這樣的靜態初始化器。全局變量由構造函數初始化。此外鏈接的文章是可怕的,充滿了非常糟糕的建議。 – 2009-10-27 06:43:57

4

簡而言之,正如你所見,是:你不能那樣做。

我想你真正想要的是這樣的:

std::map<std::string, Foo> map; 

int main() 
{ 
    map["bar"] = Foo(); 

如果你真的需要初始化執行main()之前,你會經常看到的例子是這樣的:

namespace { 
    struct StaticInitHelper { 
     StaticInitHelper() { map["bar"] = Foo(); } 
    } _helper_obj; 
} 

不過,現在您有一個新問題,即無法保證在_helper_obj之前創建了map。解決這個問題的一個方法是將它們合併:

namespace { 
    struct StaticInitHelper : public std::map<std::string, Foo> { 
     StaticInitHelper() { (*this)["bar"] = Foo(); } 
    } map; 
} 

但是,通常不推薦繼承STL容器類。請注意,此示例隱藏了其他任何構造函數,並且STL基類沒有虛擬析構函數。這被很多人認爲是「黑客」,應該避免。

另一種替代方案是用std::map定義類:

namespace { 
    struct StaticInitHelper { 
     StaticInitHelper() { map["bar"] = Foo(); } 
     std::map<std::string, Foo> map; 
    } map_holder; 
} 

map_holder.map.find(... 

但當然這所有使用地圖的複雜化。

更新:

我忘了提及的另一種選擇,使用boost::assign

#include <boost/assign/list_of.hpp> 

map<int,int> map = boost::assign::map_list_of(1,2)(2,3)(3,4)(4,5)(5,6); 

我無法找到這是否是安全的靜態對象的信息,雖然。