原创 在 Visual C++ 中控制全局对象的初始化顺序收藏

新一篇: C++ 枚举类型的思考 | 旧一篇: C++ 和 C# 构造函数的区别

在 C++ 中,同一个翻译单位(.cpp文件)里的全局对象的初始化顺序是先定义的对象先初始化(同时也后析构),但 C++ 标准并没有规定不同翻译单位间全局对象的初始化顺序。按照这个分析,以下的代码可能工作,也可能不工作(cout 是 C++ 用于输出的全局对象,和我们自己的对象位于不同的翻译单位):

class A {
    A() {
        cout << "A::A()";
    }
    ~A() {
        cout << "A::~A()";
    }
};

A a;

OK,你会说这段代码绝对运行正确,也就是说 cout 总是比我们的对象先初始化以及后析构。这是有原因的——虽然 C++ 标准并没有明确规定,但各 C++ 编译器都按照类似的方式实现了对全局对象初始化顺序的控制,否则的话,C++ 库就无法按照预期的方式工作了(如果不允许在全局对象构造函数中使用 cout 可能不少程序员会疯掉)。

Visual C++ 提供了 #pragma init_seg 这样一个编译指令来控制一个翻译单位中对象的初始化顺序。打开 Visual C++ 自带的 CRT 源代码文件 cout.cpp,你会发现如下的语句:

#pragma warning(disable: 4074)
#pragma init_seg(compiler)

_CRTIMP2 ostream cout(&fout);

通过使用 #pragma init_seg(compiler) 这个指令,在 cout.cpp 文件中的所有对象都被放在 compiler 这个初始化组,这个组中的对象总是最先初始化和最后析构。当然,这个组是保留给微软 C/C++ 运行库使用的,我们不应该使用它。在我们自己的代码里,如果希望一些对象先于其他对象初始化,我们可以使用 #pragma init_seg(lib) 指令,放置在 lib 组的对象总是比 compiler 组的对象初始化晚,但要先于其他对象。#pragma init_seg 指令还有其他一些高级用法让你进行更细致的控制。

(注:编译指令不属于标准 C++ 的特性)

发表于 @ 2004年08月07日 22:01:00|评论(loading...)|编辑

新一篇: C++ 枚举类型的思考 | 旧一篇: C++ 和 C# 构造函数的区别

评论

#贾迎乐 发表于2004-08-08 16:51:00  IP: 211.150.244.*
>>标准尽管没有对全局对象的初始化顺序做出具体的规定,但是标准规定一个全局对象一定会在它第一次被使用前初始化

如果不使用诸如 init_seg 这样的语句的话是无法保证做到一个全局对象一定会在它第一次被使用前初始化的,因为这个全局对象可能被另一个全局对象使用。象 C# 和 Java 这样的语言才可以确保做到这一点。
#windoze(瞌睡窗) 发表于2004-08-08 00:10:00  IP: 219.144.176.*
上述代码在符合标准的C++中一定可以工作,标准尽管没有对全局对象的初始化顺序做出具体的规定,但是标准规定一个全局对象一定会在它第一次被使用前初始化。至于init_seg之类的东东就是各家厂商自己的实现细节了。
#none 发表于2005-01-20 20:31:00  IP: 220.202.68.*
>>标准尽管没有对全局对象的初始化顺序做出具体的规定,但是标准规定一个全局对象一定会在它第一次被使用前初始化

标准只是说上述情况在main()函数执行之后才成立
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © 贾迎乐