zoukankan      html  css  js  c++  java
  • 转:不同编译单元内定义的non-local static 对象的初始化顺序

    《Effective C++》条款4中提到了”留意不同编译单元内的non-static变量的初始化顺序“

    下文的描述得很详细,转载过来了。

    http://blog.csdn.net/chgaowei/article/details/6001433

    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.c,Test2.c分别有两个定义:

    Test1 t1;

    Test2 t2;

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

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

    编译并执行,打印为:

    Test1 构造函数.

    Test2 test 函数

    Test2 构造函数.

    Hello World!

    Test2 析构函数.

    Test1 test 函数

    从上面的打印可以看出:

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

    2、  t1和t2的构造顺序和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 函数

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

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

  • 相关阅读:
    echarts 柱状图移除圆角
    echarts 图例显示到右边
    css图片文字一排
    linux磁盘分区、挂载、查看
    mysql的sql筛选排重最大值并修改其属性
    Java调用Linux下的shell命令并将结果以流的形式返回
    SHELL脚本中执行SQL语句操作MYSQL的5种方法
    在 Mac 上使用 `sed` 命令的几个坑
    Linux sed命令实现替换文本内容
    docker ps -a
  • 原文地址:https://www.cnblogs.com/wangpei0522/p/4459693.html
Copyright © 2011-2022 走看看