22

在类定义中初始化的静态整型数据成员可以声明为constconstexpr,但在类定义中初始化的非整型静态数据成员必须是constexpr

class MyClass {
  static const     int   w = 5;          // okay
  static constexpr int   x = 5;          // okay
  static const     float y = 1.5;        // error!
  static constexpr float z = 1.5;        // okay
};

有人知道为什么不允许声明 y 吗?标准中使其非法的部分是 9.4.2/3,但为什么它是非法的?

4

3 回答 3

4

在 C++11 之前,您无法在类声明中初始化非整数/枚举类型的静态成员(但您可以在类声明之外)。管理规则constexpr将其向前推进,但允许您constexpr在类声明中使用它来初始化它(因此您不再需要如下代码):

struct A
{
    static const float pi;
};

const float A::pi = 3.1415;

这条规则的副作用之一是简化你的类结构而不是让它变得丑陋(如上面的代码)。

在 C++11 添加之前出现这种情况的原因之一constexpr是标准没有指定如何实现浮点(它留给处理器/架构 - 例如,当您说 时float x = 1.6f,它实际上是1.6000000000024在大多数系统上)。

于 2013-10-24T20:08:19.530 回答
2

float描述动机有点困难,但想象一个班级成员:

class MySpecialInt {
public:
    constexpr MySpecialInt(const int & other) {
    }
};
class MyClass {
    static const     MySpecialInt a = 5; // error
    static constexpr MySpecialInt b = 5; // okay
};

a在这种情况下,可能会有一些可能违反(或至少严重复杂化)单一定义规则的非平凡构造。因为constexpr具有保证的限制性编译时属性,所以b的复制构造函数也必须并且constexpr因此保证在编译时返回一个明确定义的值(并且违反单一定义规则)

为什么float表现出这种行为我认为只是出于遗留原因,因为float传统上从来没有像这样初始化(“因为标准是这样说的”),所以他们抓住static const floatconstexpr.

于 2013-10-24T20:14:03.927 回答
0

这可能是因为非整数 i 也可能包含 char 之类的数据类型,这就是为什么您不能将它们设为常量并需要常量表达式的原因。但在整数的情况下,您可以将它们设为常量表达式或常量。所以,因为 char 只能是常量表达式,所以对于所有非整数值都是非法的。

于 2013-10-24T20:09:19.853 回答