c++ - 首次使用对象后调用的全局对象构造函数

标签 c++ gcc constructor global

据我所知,全局对象的构造函数需要在任何人尝试使用这些对象之前调用。但是在我的程序中,情况似乎并非如此。这是我的简化代码(我用 gcc 版本 4.6.3-1ubuntu5 编译它)

#include <iostream>

using namespace std;

struct type_data
{
    int id;

    type_data()
        : id(-1) // set some invalid id
    {
        cout << "creating a new type data" << endl;
    }
};

template <typename T>
struct type_data_for_type
{
    static type_data data;
};
template <typename T>
type_data type_data_for_type<T>::data;


struct type_registry
{
    static type_registry& instance()
    {
        static type_registry i;
        return i;
    }

    void register_type(type_data& t)
    {
        cout << "registering a type" << endl;
        t.id = last_id++;
    }

    int last_id;
};

template <typename T>
struct registrator
{
    registrator()
    {
        type_registry::instance().
            register_type(type_data_for_type<T>::data);
    }

    int unused;
    static registrator payload;
};
template <typename T>
registrator<T> registrator<T>::payload;

class foo {};

inline void register_foo()
{
    registrator<foo>::payload.unused = 1;
}

int main()
{
    cout << type_registry::instance().last_id << endl;
    cout << type_data_for_type<foo>::data.id << endl;
    return 0;
}

基本上它通过 register_foo 全局注册 foo 类型。我希望输出为:

creating a new type data
registering a type
1
0

但它是:

registering a type
creating a new type data
1
-1

这意味着我已经在调用其构造函数之前设置了 type_data 对象的 ID。

那么,这是编译器错误吗?我错过了什么吗?我可以完成这项工作吗?

最佳答案

我相信在这种情况下你不能依赖类模板的静态成员变量的初始化顺序。

此处相关的是 C++ 标准的 § 3.6.2/2:

*"静态存储持续时间的非局部变量的动态初始化是有序的或 无序的。显式专用类模板静态数据成员的定义已有序初始化。 其他类模板静态数据成员(即隐式或显式实例化特化)*具有无序初始化。”

当然还有 § 9.4.2/6,它引用了上述规则:

“静态数据成员的初始化和销毁​​与非局部变量(3.6.2、3.6.3)完全一样。”

关于c++ - 首次使用对象后调用的全局对象构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14512863/

相关文章:

c++ - 在为 Arduino UNO 编译时,Arduino IDE 使用什么链接描述文件?

c++ - 继承构造函数和大括号或等于初始值设定项

c# - 表单构造函数与 Form_Load

c++ - 视觉 C++ VC6 静态

C++ 设置指向另一个指针的指针

c++ - 在头文件中设置的所有文件中全局使用变量

gcc - 基于 GCC/LLVM 的语言何时会在 x86 Windows 上支持 SEH 异常?

c++ - 编译 wxLua(跨平台&静态)

java - Android:构造函数内部的同步()无效?

c++ - QNetworkAccessManager 的自定义 QSslSocket