使用静态初始化的副作用进行一次性初始化
Use side effect of static initialization for one-time initialization
我想初始化共享库中的一些查找表,我想看看这是否是一种有效的方法,以及它是否继续在我将要编写的更多库中使用它。
typedef std::map<std::string, int> NAME_LUT;
NAME_LUT g_mLUT;
namespace
{
bool OneTimeInit()
{
::g_mLUT.insert(NAME_LUT::value_type("open", 1));
::g_mLUT.insert(NAME_LUT::value_type("close", 2));
return true;
}
bool bInit = OneTimeInit(); // Just to make initialization happen
}
它似乎在Visual Studio和gcc(Linux)上都能正常工作。只有 gcc 抱怨bInit
没有在任何地方使用。
- 是否有可能初始化被优化(
bInit
不使用),或者语言不允许(因为副作用)。 - 它确实看起来像是处理一次性初始化的良好跨平台方式,但我不确定这是否是最佳方法。
- 将
OneTimeInit
声明为静态有意义吗?(即使用static bool OneTimeInit() {...}
),或单独使用命名空间是使其对该编译单元唯一的更好方法
我不太喜欢使用静态存储的变量的想法,但是如果您要这样做,实际上可以通过编写一个将初始化对象的函数来简化代码:
typedef std::map<std::string, int> NAME_LUT;
namespace {
NAME_LUT create_lut() {
NAME_LUT table;
table.insert(NAME_LUT::value_type("open", 1));
table.insert(NAME_LUT::value_type("close", 2));
return table;
}
}
NAME_LUT g_mLut = create_lut();
请注意,这具有所有常见的初始化顺序问题(跨不同的翻译单元,特别是动态库)
是的,这是合法的,但由于您提到它在库中,因此必须确保在其中创建此翻译的翻译将被链接:
如何在库中强制包含"未使用"的对象定义
如果您有 C++11 个初始值设定项列表,这对您来说会更好吗?
NAME_LUT g_mLUT = { {"open", 1}, {"close", 2}, };
如果bInit
被优化出来(可能,特别是如果你的库被dlopen
编辑),那么你的初始化代码将不会运行。
让用户在理智的地方(main
启动后)对库进行设置调用是否有问题?这样做可以消除代码中出现许多可能的难以调试的初始化顺序错误之一的任何可能性。如果这不是一个选项,我真的建议将 init 隐藏到具有静态本地的函数调用中,如下所示:
typedef std::map<std::string, int> NAME_LUT;
namespace
{
bool OneTimeInit(NAME_LUT& mLUT)
{
::mLUT.insert(NAME_LUT::value_type("open", 1));
::mLUT.insert(NAME_LUT::value_type("close", 2));
return true;
}
NAME_LUT& get_global_mLUT()
{
static NAME_LUT g_mLUT;
static bool bInit = OneTimeInit(g_mLUT); // Just to make initialization happen
return g_mLUT;
}
}
相关文章:
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- C++成员初始化
- 为什么在C++中首先初始化成员类
- 同时具有"聚合初始化"和"模板推导"
- 初始化具有非默认构造函数的std::数组项的更好方法
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 在C和C++中初始化结构中的数组
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 在函数内部的声明中初始化数组,并在外部使用它
- 使用静态初始化的副作用进行一次性初始化