首次使用对象后调用的全局对象构造函数
Global objects constructors called after first use of object
据我所知,在任何人尝试使用这些对象之前,需要调用全局对象的构造函数。但是,在我的程序中,情况似乎并非如此。这是我的简化代码(我用 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)完全相同。
正在发生的事情是registrator<foo>::payload
在type_data_for_type<foo>::data
之前被初始化。然而,registrator<foo>
的构造函数使用type_data_for_type<foo>::data
。
您不能依赖以任何特定顺序调用静态初始值设定项,在您的情况下,与您想要的顺序相比,它以完全错误的顺序发生。
但是,我认为根本问题是您的解决方案过于复杂。你真的需要区分type_data_for_type
和registrator
吗?类型数据对象不能自行注册吗?
相关文章:
- 类的全局对象和静态成员
- 内存清理程序报告全局对象构造中未初始化值的使用
- 私有对象的互斥体 - 全局与属性
- 将对象创建为全局/静态对象会崩溃,而本地对象不会崩溃
- 涉及全局对象的循环依赖C++
- 对象指针 c++ 的全局向量错误
- 访问类对象以与全局变量进行比较
- 是否可以在C++ (C) 中使用全局范围对象(结构)?
- C++本地/全局对象的初始化
- 从多个文件访问静态全局 WinForm UI 对象
- 哪个函数负责C++全局范围内的类对象初始化?
- 何时调用全局对象的构造函数?
- 不可变的全局对象应该声明为"const my_result_t BLAH"还是"extern const my_result_t BLAH;"?
- C++全局对象丢失值
- std::atexit 从全局对象的构造函数调用时的排序
- 有没有办法在两个共享对象之间使用相同的全局变量?
- JNI返回Java对象,可以返回本地参考,还是必须是全局
- 使创建的对象全局化 [C++]
- c++游戏加载对象/全局对象
- shared_ptr对象全局删除