首先,如果我的术语有些不精确或不正确,我很抱歉:这是我没有太多涉及的 C++ 方面。
我正在为 iOS 项目使用 Google 的稀疏哈希表实现(我正在处理共享库,因为它针对的是越狱设备):特别是,我正在使用 dense_hash_map
:我需要该模板的一个对象(命名正确吗?)作为在项目中的多个文件之间共享的结构的成员。
我需要访问__attribute__((constructor))
内的那个“对象”(即结构内的dense_hash_map)函数,共享库的构造函数。显然,问题是在 dyld 处理共享库的构造函数之后调用模板的“自动构造函数”:我只能使用 dense_hash_map
仅当我手动调用构造函数时才对象,如 mymap = dense_hash_map<const char*, int, hash<const char*>, eqstr>();
中所示里面__attribute__((constructor))
功能。
但是,模板构造函数以这种方式被调用两次,一次手动调用,一次根据 C++ 自动构造函数调用。如何在不改变模板本身设计的情况下避免这种情况?
其他奇怪的事情是:
- 如果
dense_hash_map
对象被声明为该函数内的局部变量,一切正常。 - 该问题仅发生在共享库中:简单的独立程序不受此问题的影响。
所以最后我想问的是:
- 如何声明一个模板对象并强制它手动初始化,基本上不让模板构造函数自动调用?
- 在本地/全局变量情况下,模板构造函数的处理方式如何不同?
如果我使用的术语不正确,请告诉我。希望有人能解答一下这个问题,先谢谢了!
更新:具有不同情况的示例代码。
// global dense_hash_map
dense_hash_map<const char*, int, hash<const char*>, eqstr> months;
__attribute__((constructor)) static void my_constructor_0()
{
/*
actually crashes because you need to call set_empty_key()
right after the template constructor, which has not been called
yet, at this point
*/
months.set_empty_key(NULL);
months["january"] = 31;
}
__attribute__((constructor)) static void my_constructor_1()
{
// local dense_hash_map
dense_hash_map<const char*, int, hash<const char*>, eqstr> months;
/*
doesn't crash, works as it should and the map is being initialized
correctly
*/
months.set_empty_key(NULL);
months["january"] = 31;
}
// global dense_hash_map
dense_hash_map<const char*, int, hash<const char*>, eqstr> months;
__attribute__((constructor)) static void my_constructor_2()
{
/*
works as it should but if you add a log to the template constructor,
you see it being initialized twice: the first one is the manual call
and the second one is the automatic constructor
*/
months = dense_hash_map<const char*, int, hash<const char*>, eqstr>();
months.set_empty_key(NULL);
months["january"] = 31;
}
最佳答案
阅读C++: When (and how) are C++ Global Static Constructors Called?和 http://www.parashift.com/c++-faq-lite/static-init-order.html
似乎有一种叫做“静态初始化顺序失败”的东西。初始化的顺序因编译而异,因此不确定变量在使用前何时初始化。
来自http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html的建议是创建一个包含静态变量的函数,以确保在首次使用之前进行初始化。
从此,并使用此问题中的dense_hash_map,这里是防止此问题的代码片段:
typedef dense_hash_map<const char*, int, hash<const char*>, eqstr> hashtable;
//singleton function
hashtable *month_singleton() {
static hashtable *months = NULL;
//initialization, happens on first run
if (months == NULL) {
months = new hashtable();
months.set_empty_key(NULL);
}
return months;
}
__attribute__((constructor)) static void monthly_constructor()
{
months_singleton()["january"] = 31;
}
关于c++ - 模板对象声明和初始化: manually call template constructor to bypass standard constructors calls order,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19913075/