C++ 对象的静态初始化

C++ 对象的静态初始化,c++,C++,我在main函数前面声明了一个全局对象,在main函数内部声明了一个静态对象 其中哪一个使用(或者两者都使用?)静态初始化 我听说obj1也称为static;为什么呢 只关注C++,还需要考虑静态成员的初始化。 它涉及类的静态成员。 例如,当您有: class A { // declaration of i as a static member of class A static int i; }; // initialization of static member outsi

我在main函数前面声明了一个全局对象,在main函数内部声明了一个静态对象

  • 其中哪一个使用(或者两者都使用?)静态初始化
  • 我听说obj1
    也称为static;为什么呢
    


只关注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;

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


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

这两个变量都是静态的:

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

obj2
是一个局部静态变量,首次调用函数时将对其进行初始化


Scott Meyers在《高效C++》一书中建议通过函数访问局部静态变量,而不是使用非局部静态变量。这样做可以避免所谓的静态初始化顺序问题,即一个变量可以引用另一个可能尚未初始化的变量,因为初始化发生的顺序是任意的。

我的第一个疑问是这个问题有多精确。如果静态初始化与本标准中的技术含义一起使用,则表示零初始化和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() {}
数字表示每个初始化步骤的执行顺序。编译器同时考虑静态和动态初始化的原因是它设置了初始化执行的顺序。静态初始化是在动态初始化之前执行的,所有静态初始化的对象都保证在任何动态初始化开始之前具有其值。也就是说,标准保证即使在上一个程序中
c
之后出现
d
c
的值也保证为
20

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


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

这看起来像是家庭作业,请使用适当的标记。为什么它看起来像家庭作业?因为示例看起来像教科书。不,这根本不是真的。
i
是类成员,没有任何与它的静态初始化行为有关,它与OP的情况完全不同。我不认为指出“代码<代码>静态<代码>适用于C++类成员,或者C结构不存在等价物。这是一个术语问题,所以如果要做一个SU。“静态”含义范围的界定涵盖所有的基础是很好的。静态类成员、静态类方法等等。提到这一点+0.5,Douglas Adams的典故+0.5。@jHackTheRipper:标题不是问题。请注意,这个答案自我最初的评论以来已经完全改变了。现在还不错,但仍然没有回答问题(这与班级成员无关)@HostileFork:我不明白C与任何事情有什么关系,但我想如果你只为写“42”投半票,你就会投任何东西!@HostileFork:这不是一个含糊不清的问题,这个问题说得很清楚(大卫设法理解了),这个答案与此毫无关系。一个问题或答案的当前分数应该与您投的选票完全没有关系。此外,我有37.6k的原因是,我没有比建设性地为记录堆栈溢出做出贡献更好的事情了:obj1具有静态存储,因为它是一个全局存储/名称空间成员(与函数(作用域)或类(实例)不关联))不是所有静态存储对象在程序启动时都初始化为零吗?@user974191:否,最明显的反例是字符串文本
,例如“
@MSalters:
秒(8.5/6)静态存储持续时间的每个对象在程序启动时都应在任何其他初始化发生之前初始化为零。
@MSalters:这一点都不明显。你是说
static int x=3;
不会以值
3
结束,因为它作为第一步初始化为零?+1“静态初始化命令失败”
// 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() {}