静态初始化对象

时间:2011-10-18 09:44:27

标签: c++

我有一个在main函数之前声明的全局对象和main中的静态对象。

  • 其中哪一个使用(或同时执行?)静态初始化?
  • 我听说A obj1也称为静态;这是为什么?


class A { ... };

A obj1;

int main()
{
    static A obj2;
}

4 个答案:

答案 0 :(得分:4)

obj1有静态存储空间。它将在程序启动时初始化。

obj2也有静态存储,因为你这么说。它将在main()第一次执行时初始化。

答案 1 :(得分:3)

我的第一个怀疑是这个问题有多精确。如果静态初始化与标准中的技术含义一起使用,则表示零初始化并使用常量表达式对对象初始化POD类型具有存储持续时间,与动态初始化相比,其中具有静态存储持续时间的对象的初始化以其他方式初始化。

举例说明:

// at namespace level
int f();
int a;         // 1 static: zero initialization
int b = 10;    // 2 static: initialization from constant expression
int c = f();   // 3 static (zero initialization)
               // 5 followed by dynamic (result of call to f())
int d = 20;    // 4 static: initialization
int f() { return d; }
int main() {}

该数字表示每个初始化步骤的执行顺序。编译器同时考虑静态和动态初始化的原因是它在执行初始化时设置了一个顺序。 静态初始化动态初始化之前执行,并且所有静态初始化的对象在任何动态初始化开始。也就是说,该标准保证即使d出现在上一个程序中的c之后,c的值仍保证为20

对于需要动态初始化的对象,它们在静态初始化期间(概念上)零初始化,因此在c的生命周期内,它首先被设置到0,然后重置为f()(或在此程序中为20)。 概念上是由于如果编译器可以推断出变量将获得的最终值,它可以优化动态初始化并执行简单的具有该最终值的静态初始化(在上面的代码中,编译器可以检测到c动态初始化为20,并决定将其转换为符合实现的int c = 20;中的静态初始化。在这种情况下,上面代码中的步骤3和5将合并为一个步骤3.

对于具有静态存储持续时间的局部变量,标准不使用术语静态/动态初始化,但描述需要程序中的相同行为。具有静态持续时间的局部变量是零初始化或在第一次输入块时(或之前)使用常量表达式初始化POD(与静态初始化一样),同时其余的初始化是在控件第一次通过它的声明时执行的。

答案 2 :(得分:1)

仅关注C ++,您还需要考虑静态成员的初始化。 它涉及类的静态成员。 例如,当你有:

class A {
  // declaration of i as a static member of class A
  static int i;
};

// initialization of static member outside class A
int A::i = 42;

答案 3 :(得分:1)

这两个变量都是静态的:

obj1是一个非本地静态变量,将在程序启动时初始化。

obj2是一个本地静态变量,它将在首次调用函数时初始化。

Scott Meyers在他的书“Effective C ++”中建议通过函数访问本地静态变量,而不是使用非本地静态变量。这样做可以避免所谓的静态初始化顺序问题,其中一个变量可以引用另一个因为初始化发生的任意顺序而尚未初始化的变量。