【问题标题】:When and how are static data initialized in C++?静态数据何时以及如何在 C++ 中初始化?
【发布时间】:2011-12-16 22:34:50
【问题描述】:

什么时候初始化静态数据?

我认为:

它可以被初始化 构造函数,

当它被声明时,

课外
class A::member_d = 5; //  member_d is static  

其他?

另外,文件范围静态变量什么时候初始化,函数范围静态变量什么时候初始化?

我认为它们在声明时已被初始化。

谢谢

【问题讨论】:

    标签: c++ class static constructor initialization


    【解决方案1】:

    类的静态成员在定义时被初始化。 const 整数数据类型是一个例外,可以在声明时进行初始化。何时执行此类初始化有点复杂(谷歌静态初始化惨败)。按标准:

    如果初始化推迟到 main 的第一条语句之后的某个时间点,它应该发生在与要初始化的变量在同一翻译单元中定义的任何函数或变量的第一次 odr 使用之前。

    【讨论】:

    • 静态在定义点被实例化,但直到程序启动才真正被初始化。 std::string 无法在编译时分配内存。
    • Mooing Duck:实际上比“程序开始”时要宽松一些。
    • 我认为“程序启动”是一个非常宽松的术语,所以我认为我仍然安全 :D。诚然,有些可以由编译器实例化,但这不在规范中。
    • @Mooing Duck:我相信实际的规范是“在程序启动和第一次执行包含静态的模块内的函数之间的某个时间”
    • If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use of any function or variable defined in the same translation unit as the variable to be initialized. Mind = 吹。
    【解决方案2】:

    静态存储持续时间对象初始化:

    注意:静态成员对象的初始化方式与文件范围内的对象相同。

    • 文件范围内的对象在定义点初始化。
      • 您可以认为这些都是在调用 main() 之前初始化的。
      • 请参阅下面的详细信息。
    • 函数范围内的对象在第一次执行通过定义时被初始化。
      • 即通常在第一次调用该函数时。

    对象由定义中的初始化器初始化。如果您不提供初始化程序,那么它将被初始化为零。

    int x1;        // zero initialized.
    int x2 = 5;    // initialized with 5 
    A   y1;        // Default initialized:
                   // If A has a user defined constructor this is called.
                   // If A has a compiler generated constructor then
                   // it is value-initialized which means class objects have their
                   // default constructor called and POD objects are zero-initialized
    A   y2 = A();  // Default constructed.
    A   y3(5);     // Constructor called with value 5.
    

    静态成员与文件范围内的对象完全相同。

    class Z
    {
        static int x1; // declaration;
        static int x2;
        static A   y1;
        static A   y2;
        static A   y3;
    };
    // definition
    
    int Z::x1;
    int Z::x2 = 5;
    A   Z::y1;
    A   Z::y2 = A();
    A   Z::y3(5);
    

    现在它们的初始化顺序更难定义了。该命令故意含糊不清,以允许委员会无法预见的编译器和链接器情况。

    定义在:

    3.6.2 非局部变量的初始化

    主要需要注意的是:

    具有静态存储持续时间的非局部变量在程序启动时被初始化。

    所以在大多数情况下,它们都会在输入 main 之前完全构建。

    正如其他人所指出的那样。允许编译器延迟初始化。

    3.6.2 第 4 段

    静态存储时长的非局部变量的动态初始化是否在main的第一条语句之前完成,由实现定义。

    这个添加主要是为了支持在运行时动态加载库(可以在 main 启动后动态加载)。但它确实提供了一个简单的保证,即编译中的所有静态存储持续时间对象都将在使用该编译中的任何对象或函数之前完全构造。

    3.6.2 第 5 段

    如果初始化推迟到线程初始函数的第一个语句之后的某个时间点,它应该发生在同一翻译单元中定义的线程存储持续时间的任何变量的第一次 odr-use (3.2) 之前作为要初始化的变量。

    【讨论】:

      【解决方案3】:

      全局变量在程序启动时初始化,在调用main() 之前。作用域本地的静态对象在第一次执行时初始化。

      静态类成员只是全局变量,见上文。

      main() 返回后会销毁全局和静态对象。

      (它的实现细节相当复杂,因为所有的析构函数都必须排队等待在某处执行,并且对于局部静态,需要一个标志来指示对象是否已经被实例化。)

      【讨论】:

        【解决方案4】:

        不,当然,构造函数不能初始化静态数据成员。对于 const 整数或枚举类型,您可以在类定义的范围内进行初始化。但是,一般情况下,您必须在类定义之外进行初始化。

        【讨论】:

          猜你喜欢
          • 2018-09-12
          • 2011-08-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多