"static initialization"到底是什么意思?

What exactly does "static initialization" mean?

本文关键字:意思 是什么 static initialization      更新时间:2023-10-16

我一直在C++11中阅读POD,我读过的几个地方都谈到了支持静态初始化的POD。例如:

在 StackOverflow 上:

POD 的想法基本上是捕获两个不同的属性:
1.支持静态初始化,并且
2. 在 C++ 中编译 POD 会为您提供与用 C 编译的结构相同的内存布局。

(只有粗体部分是相关的(

在维基百科上:

可以

静态初始化简单的类型。

显然我不明白什么是静态初始化。我认为制作全局变量是静态初始化的一个例子,但我可以执行以下操作,但Foo不是 POD:

#include <type_traits>
#include <iostream>
struct Foo {
  Foo() : x(0), y(0) {}
  int x;
  int y;
};
struct Bar {
  Bar() = default;
  int x;
  int y;
};
// Apparently the following two lines are not "static initialization" because
// Foo is non-POD yet we can still do this:
Foo f;
Bar b;
int main()
{
    if (std::is_pod<Foo>::value) std::cout << "Foo is a POD" << std::endl;
    else                         std::cout << "Foo is *not* a POD" << std::endl;
    if (std::is_pod<Bar>::value) std::cout << "Bar is a POD" << std::endl;
    else                         std::cout << "Bar is *not* a POD" << std::endl;
}

输出:


Foo is *not* a POD Bar is a POD

那么静态初始化到底是什么,它与琐碎的类有什么关系呢?例子会很棒。

静态初始化是使用编译时值初始化某个变量,以便该值最终被"烘焙"到"可执行映像中(无需实际运行任何代码(:

struct Foo {
  int x;
  int y;
};
Foo foo = { 0, 1 };

在上面的示例中,struct Foo是 POD,因此编译器知道其内存布局只是彼此相邻的两个整数。它还知道foo.x应初始化为 0foo.y初始化为 1 。这些信息足以生成foo应该如何查看编译时的"内存映像"并将其写入可执行映像。

稍后运行映像时,操作系统加载程序会将其内容映射到内存地址,并以这种方式使foo"活动"。重要的是,foo的"初始化"实际上已经完成,然后该过程(包括您的代码以及首先运行的 C/C++ 运行时中的代码(甚至有时间执行单个 CPU 指令。

具有静态持续时间的对象初始化分为两个过程,静态初始化和动态初始化(注意术语静态:)的滥用(。

动态初始化是指涉及调用函数的初始化,因此必须在运行时进行,而文本初始化可以存储在可执行文件本身中并刚刚加载。

静态初始化适用于具有静态或线程存储持续时间的变量。它分两个阶段发生。

首先,具有静态存储持续时间的变量在任何其他初始化之前初始化为零。

然后执行常量初始化。常量初始化必须是以下三种可能性之一 (§3.6.2/2(:

    如果具有静态或线程存储持续时间的引用的
  • 初始值设定项中显示的每个完整表达式(包括隐式转换(都是常量表达式 (5.19(,并且该引用绑定到指定具有静态存储持续时间的对象的左值或临时(请参阅 12.2(;

  • 如果
  • 具有静态或线程存储持续时间的对象由构造函数调用初始化,如果构造函数是 constexpr 构造函数,如果所有构造函数参数都是常量表达式(包括转换(,并且在函数调用替换 (7.1.5( 之后,MEM 初始值设定项和非静态数据成员的大括号或等于初始值设定项中的每个构造函数调用和完整表达式都是常量表达式;

  • 如果具有静态或线程存储持续时间的对象未由构造函数调用初始化,并且其初始值设定项中显示的每个完整表达式都是常量表达式。

任何其他初始化(甚至是全局变量的初始化(都是动态初始化。但是,编译器可以像静态初始化一样对待动态初始化,前提是这样做不会改变程序的外部可见效果,假设它可以找出正确的值(即使该值没有正式限定为常量表达式(。

constant expression的定义(不幸的是(相当长且涉及。定义的基本样式是将core constant expression定义为除符合异常列表的表达式之外的任何表达式(不幸的是,该表达式超过一页长,因此将其总结为快速且易于理解的内容并不容易(。

静态成员初始化发生在类范围内。因此,他们可以访问其他成员数据或功能。

这是引用自MSDN

有一个很好的例子说明它是如何工作的。