类型为double的静态类成员的常量表达式初始值设定项

时间:2015-06-09 20:32:48

标签: c++ c++11 c++14 static-members constant-expression

在C ++ 11和C ++ 14中,为什么我需要在以下代码段中使用constexpr

class Foo {
    static constexpr double X = 0.75;
};

而这个产生编译器错误:

class Foo {
    static const double X = 0.75;
};

和(更令人惊讶的是)这个编译没有错误?

class Foo {
    static const double X;
};

const double Foo::X = 0.75;

2 个答案:

答案 0 :(得分:9)

在C ++ 03中,我们只允许为枚举类型的const积分的静态成员变量提供类初始化器,在C ++ 11中,我们可以使用constexpr在类中初始化文字类型的静态成员。对于const变量,这个限制保存在C ++ 11中,主要是为了兼容C ++ 03,我们可以从closed issue 1826: const floating-point in constant expressions 看到这一点:

  

用常量初始化的const整数可以用在常量表达式中,但是用常量初始化的const浮点变量不能。这是故意的,与C ++ 03兼容,同时鼓励constexpr的一致使用。然而,有些人发现这种区别是令人惊讶的。

CWG最终关闭此请求而不是缺陷( NAD ),基本上说:

  

希望浮点值参与常量表达式的程序员应该使用constexpr而不是const。

对于参考N18049.4.2 [class.static.data] 部分中公开提供的最接近C ++ 03的标准草案说:

  

如果静态数据成员是const integral或const枚举类型,则它在类定义中的声明可以   指定一个常量初始化器,它应该是一个整型常量表达式(5.19)。在这种情况下,会员可以出现   在积分常数表达式中。如果在程序中使用该成员,则该成员仍应在命名空间范围内定义   命名空间范围定义不应包含初始化程序。

和草案C ++ 11标准部分9.4.2 [class.static.data] 说:

  

如果非易失性const静态数据成员是整数或枚举类型,则其在类中声明   definition可以指定一个大括号或者相等的初始化程序,其中每个initializer子句都是赋值表达式   是一个常量表达式(5.19)。可以在。中声明文字类型的静态数据成员   使用constexpr说明符的类定义;如果是这样,其声明应指定一个支撑或等于初始化器   其中作为赋值表达式的每个initializer子句都是一个常量表达式。 [...]

这在C ++ 14标准草案中几乎相同。

答案 1 :(得分:0)

类内静态const“定义”实际上是声明。当定义一个变量时,编译器会为该变量分配内存,但这不是这种情况,即获取这些静态const-in-class内容的地址是错误的,NDR。

这些东西应该用在代码中,但是浮点类型并不容易,因此不允许这样做。

通过在类外部定义静态const变量,您向编译器发信号通知这是真正的定义 - 具有内存位置的真实实例。