4

我一直在阅读 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

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

4

4 回答 4

5

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

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

于 2013-02-26T16:48:06.780 回答
5

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

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

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

  • 如果出现在具有静态或线程存储持续时间的引用的初始化程序中的每个完整表达式(包括隐式转换)都是一个常量表达式(5.19)并且该引用绑定到一个左值,该左值指定具有静态存储持续时间的对象或临时(见 12.2);

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

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

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

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

于 2013-02-26T16:53:14.600 回答
4

静态初始化是使用编译时值初始化某些变量,以便该值最终被“烘焙”到可执行映像中(不需要实际运行代码):

struct Foo {
  int x;
  int y;
};

Foo foo = { 0, 1 };

在上面的例子struct Foo中是 POD,所以编译器知道它的内存布局只是两个相邻的整数。它还知道foo.x应该初始化为0和。这些信息足以生成一个“内存映像”,说明应该如何查看编译时间并将其写入可执行映像。foo.y1foo

稍后运行映像时,操作系统加载程序将其内容映射到内存地址,并以这种方式foo“活着”。foo重要的是,在进程(包括您的代码以及首先运行的 C/C++ 运行时中的代码)有时间执行甚至一条 CPU 指令之前,“初始化”实际上已经完成。

于 2013-02-26T16:45:29.527 回答
-1

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

引用自MSDN

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

于 2013-02-26T16:49:37.147 回答