我一直在阅读C++ 11中的POD,我读过的几个地方已经说过一些关于支持静态初始化的POD.例如:
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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Foo is *not* a POD
Bar is a POD
那么究竟什么是静态初始化,它与琐碎的类有什么关系呢?例子很棒.
静态初始化是使用编译时值对某些变量进行初始化,以便该值最终被“烘焙到”可执行映像中(不需要实际运行任何代码):
struct Foo {
int x;
int y;
};
Foo foo = { 0, 1 };
Run Code Online (Sandbox Code Playgroud)
上面的例子struct Foo是POD,所以编译器知道它的内存布局只是两个相邻的整数。它还知道foo.x应该初始化为0和foo.yto 1。这些信息足以生成一个“内存映像”,说明如何foo查看编译时并将其写入可执行映像。
当稍后运行映像时,操作系统加载程序将其内容映射到内存地址,并以这种方式使foo“活动”。重要的是,“初始化”foo实际上在进程(包括您的代码以及首先运行的 C/C++ 运行时的代码)有时间执行单个 CPU 指令之前完成。
具有静态持续时间的对象的初始化分为两个阶段,静态初始化和动态初始化(注意滥用术语静态 :)).
动态初始化是指涉及调用函数的初始化,因此必须在运行时进行,与可以存储在可执行文件本身并刚加载的文本初始化相比.
静态初始化适用于具有静态或线程存储持续时间的变量 它分两个阶段发生.
首先,具有静态存储持续时间的变量在任何其他初始化之前被初始化为零.
然后执行常量初始化.常量初始化必须是以下三种可能之一(§3.6.2/ 2):
如果在具有静态或线程存储持续时间的引用的初始值设定项中出现的每个完整表达式(包括隐式转换)是常量表达式(5.19)并且引用绑定到指定具有静态存储持续时间的对象的左值或临时(见12.2);
如果具有静态或线程存储持续时间的对象由构造函数调用初始化,如果构造函数是constexpr构造函数,如果所有构造函数参数都是常量表达式(包括转换),并且在函数调用替换(7.1.5)之后,每个mem-initializers中的构造函数调用和完全表达式以及非静态数据成员的brace-or-equal-initializers是一个常量表达式;
如果具有静态或线程存储持续时间的对象未通过构造函数调用初始化,并且其初始化程序中出现的每个完整表达式都是常量表达式.
任何其他初始化(甚至是全局变量)都是动态初始化.但是,允许编译器将动态初始化视为静态初始化,前提是这样做不会改变程序的外部可见效果,假设它可以找出正确的值(即使该值不是官方有资格作为常数表达).
constant expression(不幸的是)a的定义相当长且涉及.定义的基本样式是将a定义core constant expression为任何表达式,除了那些拟合异常列表的表达式(不幸的是,这些表达式不仅仅是页面长度,因此将其概括为快速且易于理解的内容并不容易).
| 归档时间: |
|
| 查看次数: |
392 次 |
| 最近记录: |