强制静态成员初始化
我有一个类,它包含一个静态成员,一个字符串映射到函数指针。该映射旨在用一组静态映射填充一次,并且不会随后进行修改。强制静态成员初始化
我的问题是,如何确保地图在初始化之前不被访问?我的代码目前看起来是这样的:
class MyClass
{
static MapType s_myMap;
public:
static const MapType& getTheMap()
{
if (s_myMap.empty())
{
// Populate the map
}
return s_myMap;
}
};
,工作正常进行的MyClass
外部客户,但并不妨碍内部类成员直接访问private
地图已经初始化之前。
为了解决这个问题,我想制作地图本地的getter方法的:
class MyClass
{
public:
static const MapType& getTheMap()
{
static MapType s_myMap;
if (s_myMap.empty())
{
// Populate the map
}
return s_myMap;
}
};
这是一个好主意,或者是有实现这一目标的一个更好的办法?
将静态函数移入该函数将解决初始化问题的任何顺序 ,但它可能会使您的订单损坏一个,即 。在许多情况下,最好使用指针和动态分配,以便映射永远不会被破坏。
至于初始化它,我经常使用两个迭代器的构造函数,所以我可以使这个映射本身为const。要做到这一点,只是定义 struct
用转换操作符,是这样的:
struct MapInitData
{
char const* key; // Or whatever type is needed.
char const* value; // Or whatever type is needed.
operator MapType::value_type() const
{
return MapType::value_type(key, value);
}
};
MapInitData const mapInitTable[] =
{
{ "key1", "value1" },
// ...
};
MapType const ourMap(begin(mapInitTable), end(mapInitTable));
这真是太棒了 - 我真的想把地图制作成'const',但是我不认为我能够做到。 – atkins
我讨厌这个建议(关于指针和动态分配)。销毁问题的顺序很容易解决。 http://stackoverflow.com/questions/335369/finding-c-static-initialization-order-problems/335746#335746。 –
@LokiAstari我没有看到那里的代码解决任何问题。销毁顺序仅在特定的对象子集内排序,如静态声明的那些。假设你有一个'static std :: auto_ptr
如果在全局/ namespace
范围内没有调用MyClass::getTheMap()
,那么在初始化之前您不必担心使用的数据成员static
。
不过,如果上述static
方法getTheMap()
在全球/ namespace
范围使用:
SomeGlobal object = MyClass::getTheMap();
那么你目前的做法似乎是罚款。
我对“initialise”一词有点宽松。我的意思是,在访问之前,地图应该填入一组条目。数据成员使用'MapType MyClass :: s_myMap = MapType()',以更精确的方式初始化为空映射。 – atkins
@atkins:如果你还没有首先陷入未定义的行为,那么getTheMap()会正确地设置条目。问题在于,使用全局静态变量很容易陷入未定义的行为。 –
你的函数“getTheMap”应该有一个线程安全中有一个锁。将其移到本地功能是一个好主意。
我认为这与drdobbs文章“C++和双重检查锁定的危险”http://drdobbs.com/cpp/184405726类似于这个问题。在这里他通过使用案例和不同类型的单身人士安全其他模式与threadsafety。
至于破坏,你需要摧毁它吗?
将静态移动到函数是一个好主意。只要没有其他的静态对象初始化调用'getTheMap',你就没事。 –
地图是否动态初始化?如果没有,你可以将它填充到初始化程序中(假设你有最近的编译器)。 –
@KerrekSB它是静态初始化的。为了检查我已经理解了你,你是否建议将'//填充地图'所隐含的代码移动到一个单独的初始化方法(例如'initialiseMap()'),然后通过'MapType MyClass :: s_myMap = initialiseMap()'? – atkins