在 C + + 11之前,我们只能对整数或枚举类型的静态 const 成员执行类内初始化。Stroustrup 在他的 C + + FAQ 中讨论了这一点,举例如下:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
理由如下:
那么,为什么会存在这些不便的限制呢?类通常在头文件中声明,而头文件通常包含在许多翻译单元中。但是,为了避免复杂的链接器规则,C + + 要求每个对象都有唯一的定义。如果 C + + 允许在类中定义需要作为对象存储在内存中的实体,那么这个规则就会被打破。
然而,C + + 11放宽了这些限制,允许在类内初始化非静态成员(12.6.2/8) :
在非委托构造函数中,如果给定的非静态数据成员或基类不是由 Mem-initializer-id指定的(包括因为构造函数没有 Ctor 初始化程序而没有 Mem-initializer-list的情况) ,并且实体不是抽象类的虚拟基类(10.4) ,那么
- 如果该实体是具有 大括号或等于初始值设定项的非静态数据成员,则按8.5中指定的方式初始化该实体;
- 否则,如果该实体是变体成员(9.5) ,则不执行初始化;
- 否则,该实体将被默认初始化(8.5)。
第9.4.2节还允许在类内初始化使用 constexpr
说明符标记的非常量静态成员。
那么,我们在 C + + 03中受到限制的原因是什么呢?我们只是简单地接受“复杂的链接器规则”,还是改变了一些其他的东西,使其更容易实现?