zoukankan      html  css  js  c++  java
  • C++从静态对象的初始化顺序理解static关键字

    问题

    首先考虑一个全局变量的初始化顺序问题

    在头文件1中:

    extern int b;
    int a = b + 1;

    在头文件2中:

    extern int a;
    int b = a + 1;

    源文件中包含了头文件1和头文件2,这种情况下a和b可能的值是什么呢?

    虽然在开发过程一般不会出现上述这种情况,但是这核心的是一个全局变量初始化顺序的问题,这个问题在团队开发过程可能会碰到。

    可以使用static的特性来解决此问题,static关键字作用一般有以下几点:

    1. 静态全局变量,变量在该翻译单元是可见的,但是在其他翻译单元中是不可见的(翻译单元暂时理解为源文件,后文解析)。如下:

    //源文件1中
    static int n;
    //源文件2中
    extern int n;//这里编译无错,但链接出错,因为源文件1中的n是外部不可见的

    2. 静态局部变量,变量虽然是一个局部变量,但是它在全局变量区分配内存,该变量在局部可见,并且只初始化一次。

    3. 静态函数,和静态全局变量一样,该翻译单元可见,外部不可见。

    4. 类中静态成员变量,变量需要在类外部声明,所有类的对象共用一个静态成员变量。

    5. 类中静态成员函数。

    解决方式

    Initializer.h中:

    #ifndef INITIALIZER_H
    #define INITIALIZER_H
    #include <iostream>
    extern int x;
    extern int y;
    
    class Initializer
    {
        static int initCount;
    public:
        Initializer() 
        {
            std::cout << "Initializer()" << std::endl;
            if (initCount++ == 0)
            {
                std::cout << "performint initialization"
                    << std::endl;
                x = 100;
                y = 200;
            }
        }
        ~Initializer()
        {
            std::cout << "~Initializer()" << std::endl;
            if (--initCount == 0)
            {
                std::cout << "performint cleanup"
                    << std::endl;
            }
        }
        void testFun()
        {
            std::cout << "testFun"<< initCount << std::endl;
        }
    private:
    
    };
    static Initializer init;
    #endif

    Initializer.cpp

    #include "Initializer.h"
    
    int x;
    int y;
    int Initializer::initCount;

    其他cpp文件只需要包含头文件即可自动解决x和y的初始化顺序问题。

    #include "Initializer.h"

    在Initializer.h定义了一个静态全局变量,这个变量在一个翻译单元是内部可见的,所以Initializer.cpp和所有包含Initializer.h的源文件中都会又有一个init变量,这个变量虽然名称相同,但是每个翻译单元的init变量地址是不同的。不理解的话可以考虑下面代码的输出:

    header.h中:

    static int nCount = 1;

    fun.cpp中:

    #include "header.h"
    #include <iostream>
    void fun()
    {
        std::cout << "enter fun:" << &nCount << "	" << nCount << std::endl;
        nCount++;
        std::cout << "leave fun:" << &nCount << "	" << nCount << std::endl;
    }

    main.cpp中:

    #include "header.h"
    #include <iostream>
    extern void fun();
    
    int main()
    {
        std::cout << "enter main:" << &nCount << "	" << nCount << std::endl;
        fun();
        std::cout << "leave main:" << &nCount << "	" << nCount << std::endl;
        return 0;
    }

    header.h中定义了一个静态全局变量,fun.cpp是一个翻译单元,编译fun.cpp时,nCount是一个内部可见(fun.cpp内可见)的全局变量。编译main.cpp时,nCount是一个内部可见(main.cpp内可见)的全局变量,这两个变量虽然变量名是一样的,但是地址是完全不同的。

    输出如下:

    image

  • 相关阅读:
    (原创)常用加密解密
    Winforms和资源(Resources/resx)
    delphi中的第三方控件如何安装 (转)
    IT博客
    访问FTP (转)
    设置radasm,使其支持8086 16位asm(转)
    EditPlus注册码(转)
    windows资源管理器已停止工作 (转)
    当发生异常时,怎样能不让‘delphi的异常提示框出现’而出现自己的‘异常提示框’?
    清除复制网页带过来的背景颜色 (转)
  • 原文地址:https://www.cnblogs.com/Reyzal/p/7230169.html
Copyright © 2011-2022 走看看