【发布时间】:2018-12-19 09:58:53
【问题描述】:
我想知道是否可以确保仅在程序的静态初始化步骤中调用函数?
例如,假设我有一些单例类,它包含一个 std::map 对象并公开了它的 insert 和 at 方法。我想确保从中读取数据(at 方法)是线程安全的,据我了解,这需要确保没有任何东西在修改数据(即使用 insert 方法)。
地图打算在静态初始化期间仅被填充,此时我假设只有一个线程。一旦main() 开始,我有什么方法可以确保没有误导用户调用insert?
示例代码
#include <map>
#include <string>
class Singleton {
private:
std::map<std::string, std::string> m_map;
public:
static Singleton& instance() {
static Singleton theSingleton;
return theSingleton;
}
static bool insert(const std::string& key, const std::string& value) {
return instance().m_map.insert(std::make_pair(key, value) ).second;
}
static std::string at(const std::string& key) {
return instance().m_map.at(key);
}
};
static bool inserted = Singleton::insert("Hello", "World"); // fine
bool addItem(const std::string& key, const std::string& value) {
return Singleton::insert(key, value); // not OK
}
不用说(?)实际代码比这个简单的例子要复杂得多。
解决方案后编辑:看起来尽可能安全的最佳方法是维护一个status 变量,该变量记录单例是处于“插入”还是“读取”模式并采取相应行动。感谢大家的意见和建议!
【问题讨论】:
-
如何让 insert 成为一个用构造函数调用的私有函数并使映射为 const?
-
@AdamZahran 原则上应该允许其他翻译单位向地图添加信息(只要他们在 main 之前添加)。
-
这似乎不是一个很好的设计选择,因为在这种情况下地图内容有点不可预测,例如如果在两个不同的编译单元中使用相同的键插入两个不同的值,哪一个最终会出现在 map 中?
-
你会在地图完全初始化之前 *read 吗?换句话说,
at方法会在 main 之前被调用吗? -
@liliscent
at不应在 main 之前调用(或者至少我看不出有任何理由 + 如果有必要,我可以将此作为要求)。我可以保证没有insert调用应该依赖于任何at调用。
标签: c++ c++11 static-initialization