我可以在标头中使用静态const float和值初始化

时间:2018-05-30 09:06:19

标签: c++ c++11 c++14

我有这个问题困扰我。

为什么我的.hpp文件中没有这样的代码。

class H {
  private:
    static const int i =5;
    static const float f = 1.0;
    static const string s = "string";
}

只能声明和初始化int,bool,enum和constexpr等。

我的问题:

  1. 为什么字符串和其他复杂数据类型需要在cpp中正确初始化?它们是不变的。

  2. 为什么我们对浮点数和整数有不同的行为?我的猜测:gcc不支持,但如果我们使用constexpr,可以很容易地支持。

1 个答案:

答案 0 :(得分:1)

这是因为标准是这样说的。

通常,out-of-line定义规则适用于static const成员:

  

在其类定义中声明static数据成员定义。

唯一的例外是,因为C ++ 11 integral和enum static const类型可以在线初始化。

[class.static.data]/3(强调我的):

  

如果非易失性const static数据成员属于整数枚举类型,则其在类定义中的声明可以指定大括号 - or-equal-initializer ,其中 assignment-expression 的每个 initializer-clause 都是一个常量表达式。

作为Bjarne mentioned

  

为什么存在这些不方便的限制?类通常在头文件中声明,并且头文件通常包含在许多翻译单元中。但是,为避免复杂的链接器规则,C ++要求每个对象都有唯一的定义。如果C ++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏。

理性可能是整数类型成为编译时常量,虽然我倾向于不同意,因为编译单元中单个地址的规则仍然适用,这意味着编译器仍然必须发出static const成员弱链接并让链接器折叠它们,就像使用多重定义的模板一样。此时对整体类型的限制变得没有实际意义,因为相同的折叠可以应用于任何类型。事实上,C ++ 17"修复"它与inline成员:

class H {
private:
    inline static const int i = 5;
    inline static const float f = 1.0;
    inline static const string s = "string";
};