c++ - 模板对象声明和初始化: manually call template constructor to bypass standard constructors calls order

标签 c++ templates constructor

首先,如果我的术语有些不精确或不正确,我很抱歉:这是我没有太多涉及的 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对象被声明为该函数内的局部变量,一切正常。
  • 该问题仅发生在共享库中:简单的独立程序不受此问题的影响。

所以最后我想问的是:

  1. 如何声明一个模板对象并强制它手动初始化,基本上不让模板构造函数自动调用?
  2. 在本地/全局变量情况下,模板构造函数的处理方式如何不同?

如果我使用的术语不正确,请告诉我。希望有人能解答一下这个问题,先谢谢了!

更新:具有不同情况的示例代码。

// 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/

相关文章:

c++ - 拦截服务器和客户端中的 gRPC C++ 调用

c++ - 初始化一个动态 vector 列表

c++ - 模板特化 vs 在模板参数类型上使用 if else

android - 我可以创建一个 android 应用程序作为模板吗?

c++ - 如何在类中初始化 vector ?

java - 当年龄不在范围内时抛出用户定义的异常

C++ 静态构造函数返回一个容器

c++ - 模板类中的循环依赖

c++ - 我应该通过套接字以一次读\写还是多个 block 的方式发送文件?

C++ 成员函数的无效使用,你是不是忘记了( )?