不同编译单元内定义的non-local static 对象的初始化顺序

static对象包括global对象,定义于namespace作用域的对象,在class内的对象,在函数内,以及file作用域内被声明为static的对象。

local-static 对象指的是定义在函数内部的对象。其他的被称为non-local-static对象。

编译单元是指产生单一目标文件的代码,通常是一个源程序和它所include的头文件。

问题

有两个类的定义:

class Test1

{

    public :

        Test1()

        {

            printf("Test1 构造函数./n");

          t2.test();

        }

        virtual

        ~Test1( )

        {

            printf("Test1 析构函数./n");

        }

        void test()

        {

            printf("Test1 test 函数/n");

        }

};

class Test2

{

    public :

        Test2()

        {

            printf("Test2 构造函数./n");

        }

        virtual

        ~Test2( )

        {

            printf("Test2 析构函数./n");

        }

        void test()

        {

            printf("Test2 test 函数/n");

        }

};

int main()

{

printf("Hello World!/n");

return 1;

}

两个源文件:Test1.cTest2.c分别有两个定义:

Test1 t1;

Test2 t2;

测试环境为linux AS5.0GCCMakefile文件中编译顺序为:Test2.c, Test1.c

t1t2non-local static变量,他们的构造是在main函数之前进行的。

编译并执行,打印为:

Test1 构造函数.

Test2 test 函数

Test2 构造函数.

Hello World!

Test2 析构函数.

Test1 test 函数

从上面的打印可以看出:

1、  t1t2non-local static变量,他们的构造是在main函数之前进行的。

2、  t1t2的构造顺序和Makefile中编译时文件名的顺序相反。

3、  析构函数在main函数退出时进行。且析构顺序和构造顺序正好相反。

4、  由于t1构造函数中调用了non-local static变量t2,而t2此时还没有进行构造。可能会造成严重的后果。

为了避免在对象构造前访问,可以更改Makefile中编译单元的编译顺序来解决。

除此之外,还有一个更好的方法:

将每个non-local static对象搬到自己的专属函数内,这些函数返回一个指向对象的reference,而不再直接访问对象。

Test1 *GetT1()

{

    static Test1 t1;

 

    return &t1;

}

Test2 *GetT2()

{

    static Test2 t2;

 

    return &t2;

}

同时,Test1的构造函数更改为:

        Test1()

        {

            printf("Test1 构造函数./n");

          GetT2->test();

        }

这样,无论Makefile中编译单元的前后顺序如何,t1构造时访问t2时,可以确保t2已经被构造:

Test1 构造函数.

Test2 构造函数.

Test2 test 函数

Hello World!

Test2 析构函数.

Test1 test 函数

另外,这种方法还可以减少全局变量的个数,使对变量的使用可以监控。

注:t1t2也可以定义为static,不过这样在引用t2的时候需要费点周折。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值