首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >首次使用对象后调用的全局对象构造函数

首次使用对象后调用的全局对象构造函数
EN

Stack Overflow用户
提问于 2013-01-25 07:38:12
回答 2查看 346关注 0票数 0

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

代码语言:javascript
运行
复制
#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类型。我希望输出是:

代码语言:javascript
运行
复制
creating a new type data
registering a type
1
0

但事实并非如此:

代码语言:javascript
运行
复制
registering a type
creating a new type data
1
-1

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

那么,这是一个编译器错误吗?我是不是遗漏了什么?我能让它工作吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-25 07:54:21

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

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

*“具有静态存储持续时间的非局部变量的动态初始化可以是有序的,也可以是无序的。显式专门化类模板静态数据成员的定义具有有序初始化。其他类模板静态数据成员(即,隐式或显式实例化的专门化)* unordered __。”

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

静态数据成员的初始化和销毁方式与非局部变量(3.6.2、3.6.3)完全相同。

票数 4
EN

Stack Overflow用户

发布于 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_typeregistrator吗?类型数据对象不能注册自身吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14512863

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档