• C/C++之全局、static对象/变量的初始化问题


    关于全局、static对象/变量的初始化问题
    1. 全局变量、static变量的初始化时机:main()函数执行之前(或者说main中第一个用户语句执行之前)。
    2. 初始化顺序
    1)全局对象、外部static对象
        a)同一编译单元(同一源文件)中,按照对象/变量的定义顺序初始化。
        b)不同编译单元,C++标准未保证初始化先后顺序,只保证都在main()之前初始化完成。
    2)函数内部local static变量,在该函数调用过程中第一次遇到该static变量时初始化。
     
         基于以上观点,大师们建议少用全局变量,全局变量之间要消除依赖关系——特别是初始化依赖关系!
         全局变量的使用可以参考 Scott Meyers 在《More Effective C++》中M34所说的,模拟Singleton模式,通过函数内部的local static变量来代替全局变量。
         写个示例程序验证下这些变量的初始化,中间的注释部分就作为上面结论的一些补充吧。

    class CA
    {
    public:
         class CInner
         {
         public:
              CInner()
              {
                   cout << "constructor of inner class CInner." << endl << endl;
              }
         };
    public:
         CA()
         {
              cout << "Constructor of CA." << endl;
              cout << " m_i1 = "  << m_i1
                      << ", m_i2 = " << m_i2
                      << ", m_i3 = " << m_i3
                      << ", m_i4 = " << m_i4 << endl << endl;
         }
         static void Func1()
         {
              cout << " In function Func1()." << endl;
              static CInner myInner1;
         }
         static void Func2()
         {
              cout << " In function Func2(), m_i1 = " << m_i1 << endl;
              if(m_i1 < 10)
              {
                   cout << "m_i1 < 10 and Constructor of CInner won't be called!" << endl << endl;
                   return;
              }
              static CInner myInner2;
         }
    public:
         static int m_i1;
         static int m_i2;
         static const int m_i3;
         static int m_i4;
    };
    /* 不同模块的全局、static变量/对象初始化顺序不确定;
     * 同一个编译模块按定义顺序初始化。
     * 但有一点相同,就是它们均在编译期已分配好内存。
     * 对于诸如基本数据类型,编译期能确定其值的,编译器就直接将值写入分配的空间,如“CA::m_i1=3"。
     * 对于编译期不能确定值的,要等到运行时main函数之前初始化,如theCA、CA::m_i2。
     * 但若static的初始化表达式均为const或字面常量等确定的值,则亦能在编译期确定值,如m_i4。
     */

    int CA::m_i1 = 1;
    CA theCA;
    const int  CA::m_i3 = 3;
    int CA::m_i2 = CA::m_i1 + 1;
    int CA::m_i4 = CA::m_i3 + 1;
    int main(int argc, _TCHAR* argv[])
    {
         CA::Func1();
         CA::Func2();
         cout << "After CA::m_i1 increased by 11 :" << endl;
         CA::m_i1 += 11;
         CA::Func2();
         return 0;
    }

    以上程序运行结果为:
    Constructor of CA.
     m_i1 = 1, m_i2 = 0, m_i3 = 3, m_i4 = 4
     In function Func1().
    constructor of inner class CInner
     In function Func2(), m_i1 = 1
    m_i1 < 10 and Constructor of CInner won't be called!
    After CA::m_i1 increased by 11 :
     In function Func2(), m_i1 = 12
    constructor of inner class CInner.
  • 相关阅读:
    Docker系列——InfluxDB+Grafana+Jmeter性能监控平台搭建(一)
    Centos7网络配置——设置固定ip
    Fiddler扩展——自定义列数据&Tunnel to 443解决办法
    Jmeter二次开发——自定义函数
    net5学习笔记---依赖注入
    Spring Cloud Alibaba系列之分布式服务组件Dubbo
    Spring5.0源码学习系列之事务管理概述
    C# 无需管理员权限提示,操作C盘文件
    WPF 屏幕点击的设备类型
    WPF Button MouseDown事件
  • 原文地址:https://www.cnblogs.com/ht-927/p/4726551.html
Copyright © 2020-2023  润新知