[百度空间] [转] 在 Visual C++ 中控制全局对象的初始化顺序

from: http://blog.csdn.net/classfactory/archive/2004/08/07/68202.aspx

在 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++ 的特性)

时间: 2024-10-29 19:12:18

[百度空间] [转] 在 Visual C++ 中控制全局对象的初始化顺序的相关文章

不存在继承关系各类中、不存在对象引用的对象创建初始化顺序

实例3 class One   {        One(String str)      {        System.out.println(str);       }    } class Two   {       One one_1 = new One("one-1");       One one_2 = new One("one-2");       One one_3 = new One("one-3");      Two(S

读书笔记-JavaScript中的全局对象

对于任何JavaScript程序,当程序开始运行时,JavaScript解释器都会初始化一个全局对象以供程序使用.这个JavaScript自身提供的全局对象的功能包括: 1.全局对象拥有一些常用的属性值.比如undefined.Infinity以及NaN.2.全局对象拥有一些常用的属性对象.比如Math.JSON和Number对象均为该全局对象的属性.3.全局对象提供一些全局函数供调用.比如isNaN().isFinite().parseInt()和eval()等.4.全局对象提供一些全局构造器

3.Java继承中父类与子类的初始化顺序

在 Java 编程语言中,对象的初始化是非常结构化的,这样做是为了保证安全.在前面的模块中,看到了当一个特定对象被创建时发生了什么.由于继承性,对象被完成,而且下述行为按顺序发生: 存储空间被分配并初始化到 0 值 进行显式初始化 调用构造方法 层次中的每个类都会发生最后两个步骤,是从最上层开始. Java 技术安全模式要求在子类执行任何东西之前,描述父类的一个对象的各个方面都必须初始化.因此,Java 编程语言总是在执行子构造方法前调用父类构造方法的版本.有继承的类在运行的时候,一定要记得:初

Node中的全局对象

global global顶级对象,类似于浏览器中的window 在任何地方可以直接使用,不需要导包 setTimeout/setImmediate/process.nextTick,异步的时候setTimeout的优先级高于setImmediate,process.nextTick优先级最高 setInterval 在REPL环境中定义的变量直接挂载到global中 在js文件中定义的变量不会挂载到global中 获取路径 __dirname 当前执行的js所在的文件夹 __filename

Node中的全局对象和全局变量

这个文章主要是对上一个文章的扩充 util对象 在Node环境已经安装好的前提下,使用util中已经定义的方法,只需要require('util')即可: uti是utility(功效,用途)的缩写.这util模块的设计主要是为了满足Node内部API的需求.下面来介绍两个比较重要的: 1.inherits 这个方法实现了原型链之间的继承(即JavaScript的继承) var util = require('util'); function base(){ this.name = 'helio

java中对象的初始化顺序

class HelloA { public HelloA() { System.out.println("HelloA"); } { System.out.println("I'm A class"); } static { System.out.println("static A"); }}public class HelloB extends HelloA { public HelloB() { System.out.println(&quo

百度空间代码大全

display:nonecss全能隐藏代码 背景{}中添加background: url(图片地址)repeat注:repeat 背景图像在纵向和横向上平铺no-repeat 背景图像不平铺repeat-x 背景图像在横向上平铺repeat-y 背景图像在纵向平铺 line-height: 25.2px;">超链接自定义设置超链接的属性就是在相关栏目名称后面+上a{}的属性 color:#颜色代码或颜色英文名称 定义超链接字体的颜色font-family:字体名称 定义超链接字体font-

去除 Visual Studio 中臃肿的 ipch 和 sdf 文件

使用VS2010建立C++解决方案时,会生成SolutionName.sdf和一个叫做ipch的文件夹,这两个文件再加上*.pch等文件使得工程变得非常的庞大,一个简单的程序都会占用几十M的硬盘容量,可惜毕竟硬盘还没有廉价到免费的地步. 那么,该怎么解决呢?其实可以关闭它.方法: Tools->Options->Text Editor->C/C++->Advanced->Disable Database,设置为True 但是这样的办法会产生另外的一些问题,可能会导致其他的一些

Java中四大代码块的运行顺序(附code)

验证证的方法是写code.例如以下: public class test { static class A { public static String name = "hello"; static { System.out.println("A static block1"); //1 } { System.out.println("A block3"); //3 } public A() { System.out.println("