据我所知,在任何人尝试使用全局对象之前,都需要调用这些对象的构造函数。然而,在我的程序中,情况似乎并非如此。这里是我的简化代码(我用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。
那么,这是一个编译器错误吗?我是不是遗漏了什么?我能让它工作吗?
发布于 2013-01-25 07:54:21
我相信在这种情况下,你不能依赖类模板的静态成员变量的初始化顺序。
与此相关的是C++标准的§3.6.2/2:
*“具有静态存储持续时间的非局部变量的动态初始化可以是有序的,也可以是无序的。显式专门化类模板静态数据成员的定义具有有序初始化。其他类模板静态数据成员(即,隐式或显式实例化的专门化)* unordered __。”
当然还有§9.4.2/6,它引用了上面的规则:
静态数据成员的初始化和销毁方式与非局部变量(3.6.2、3.6.3)完全相同。
发布于 2013-01-25 08:27:58
发生的事情是在type_data_for_type<foo>::data
之前初始化registrator<foo>::payload
。但是,registrator<foo>
的构造函数使用type_data_for_type<foo>::data
。
你不能依赖静态初始化器以任何特定的顺序被调用,在你的例子中,它发生的顺序与你想要的完全不同。
然而,我认为潜在的问题是您的解决方案过于复杂。你真的需要区分type_data_for_type
和registrator
吗?类型数据对象不能注册自身吗?
https://stackoverflow.com/questions/14512863
复制相似问题