zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    commit(), commitNow()和commitAllowingStateLoss()
    Android 7.0 Nougat牛轧糖 发布啦
    Android Weekly Notes Issue #219
    Android Weekly Notes Issue #218
    CoordinatorLayout, AppBarLayout, CollapsingToolbarLayout使用
    Using Dagger2 in Android
    冰雪奇缘,白色世界:四个IT人的四姑娘山双桥沟游记
    你必须知道的容器日志 (2) 开源日志管理方案 ELK/EFK
    你必须知道的容器日志 (1) Docker logs & logging driver
    2019 .NET China Conf:路一直都在,社区会更好
  • 原文地址:https://www.cnblogs.com/ht-927/p/4726551.html
Copyright © 2011-2022 走看看