static const double不能有类内初始值设定项.为什么会这样?

sre*_*ree 31 c++

具有以下代码的问题是"const double"类型的静态成员,不能具有类内初始化程序.为什么仅适用于以下代码中的'const double'?请帮我.

class sample{
   static const char mc = '?';
   static const double md = 2.2;
   static const bool mb = true;
};
const char sample::mc;
const double sample::md;
const bool sample::mb;
int main(){
}
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 47

C++ 03语言标准实现的逻辑基于以下原理.

在C++中,初始化程序是对象定义的一部分.你在类中为静态成员写的内容实际上只是一个声明.因此,正式来说,直接在类中指定任何静态成员的初始值设定项是"不正确的".它违背了该语言的一般声明/定义概念.无论如何,您在类中声明的静态数据都必须在以后定义.在那里,您将有机会指定初始化程序.

此规则的一个例外是静态整数常量,因为C++中的这些常量可以形成积分常量表达式(ICE).ICE在语言中起着重要作用,为了使它们按预期工作,必须在所有翻译单元中显示积分常数的值.为了使某些常量的值在所有翻译单元中可见,它必须在声明点处可见.为了实现这一点,该语言允许直接在类中指定初始化程序.

此外,在许多硬件平台上,常量整数操作数可以直接嵌入到机器命令中.或者可以完全消除或替换常数(例如,乘法8可以实现为移位3).为了便于生成具有嵌入操作数和/或各种算术优化的机器代码,重要的是使所有转换单元中的积分常数值可见.

非整数类型没有任何类似于ICE的功能.此外,硬件平台通常不允许将非整数操作数直接嵌入到机器命令中.因此,上述"规则的例外"并未扩展到非整数类型.它什么都不会实现.

  • @anton_rh:好问题。我不知道为什么纯粹从概念上不允许它。至于实际考虑,大多数平台根本无法嵌入浮点常量(现在仍然不能)。原因之一可能是浮点常量对于这种嵌入来说太大了。然而,在 C++11 中,`constexpr` 允许你至少在概念上解决这个限制。 (3认同)
  • 为什么双打规则没有这样的例外?将浮动常量嵌入到机器命令中没有意义吗? (2认同)

Luc*_*ore 13

在C++ 11之前,只能在类定义中直接初始化const整数类型.这只是标准规定的限制.

使用C++ 11,这不再适用.

  • @Luchian Grigore:只要我们特别谈论`static const`,C++ 11就没有变化.在这方面,静态成员的规则几乎没有变化.`static const double`仍然无法在类中初始化,即使在C++ 14中也是如此.`constexpr`是一个不同的故事 - 它支持立即初始化器. (4认同)

ant*_*_rh 11

编译器让我使用constexpr而不是const:

static_consts.cpp:3:29: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double sample::md’ of non-integral type [-fpermissive]
static_consts.cpp:7:22: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double sample::md’ of non-integral type [-fpermissive]
Run Code Online (Sandbox Code Playgroud)

我刚接受了这个提议:

class sample{
   static const char mc = '?';
   static constexpr double md = 2.2;
   static const bool mb = true;
};
const char sample::mc;
const bool sample::mb;
int main(){
}
Run Code Online (Sandbox Code Playgroud)

现在它编译得很好(C++ 11).

  • 您的编译器比我的编译器(MSVC++)更有用! (3认同)