为什么“内联”静态consts不允许的,除非整数?
-
19-09-2019 - |
题
<强>可能重复强>结果 为什么我不能有在一类的非整静态const成员?
struct Example
{
static const int One = 1000; // Legal
static const short Two = 2000; // Illegal
static const float Three = 2000.0f; // Illegal
static const double Four = 3000.0; // Illegal
static const string Five = "Hello"; // Illegal
};
<强>是否有任何理由,其#2,#3,#4和#5是非法吗
我想我知道了#5的原因:编译器需要一个“真正的”字符串对象(因为它不是一个内置式),不能与mindlessy更换Five
作为"Hello"
如果是#define Five "Hello"
。但是,如果是这样的话,不能在编译器留下一丝的.OBJ文件,并告诉链接自动创建string Five
的一个实例的地方?
有关#3,#4和#尤其是2(笑!)......我实在看不出任何可能的原因!花车和双打都内置类型,就像int是!和短仅仅是一个(可能)更短的整数。
修改:我使用Visual Studio 2008进行编译。我认为所有的编译器表现在这种情况下是相同的,但显然克++编译细(除#5)。 VS给出了该片段的错误是:
error C2864: 'Example::Two' : only static const integral data members can be initialized within a class error C2864: 'Example::Three' : only static const integral data members can be initialized within a class error C2864: 'Example::Four' : only static const integral data members can be initialized within a class error C2864: 'Example::Five' : only static const integral data members can be initialized within a class
解决方案
int和短是合法的,如果你的编译器不允许他们那么你的编译器是胸围:
9.4.2 / 4:...如果静态数据成员是常量积分或const的 枚举类型,它在声明 类定义可以指定 恒定初始化其中应是整数表达式中。
我认为,浮点型和双不经特殊处理如在C ++标准常数,在整体的类型的方式,其原因在于C ++标准是警惕上浮点和双精度算术运算可能是微妙的编译机器上的不同,比他们执行该代码的机器上。编译器来评估一个常量表达式等(A + B),它需要得到相同的答案,该运行时会得到。
这是不是这么多的整数的一个问题 - 你可以效仿的整数运算,如果它不同于相对便宜。但对于编译器模拟目标设备上的浮点硬件可能是非常困难的。它甚至可能是不可能的,如果有不同版本的芯片和编译器不知道该代码将运行。这就是你开始与IEEE舍入模式搞乱甚至之前。所以避免了标准要求,所以,它没有拥有时定义和如何编译时评估可以从运行时求值不同。
作为布赖恩提到,C ++ 0X会与constexpr
解决这个问题。如果我是正确的关于原动机,然后大概10多年来一直足够长的时间渡过难关工作在指定这个东西。
其他提示
这两个Example::One
和Example::Two
应该编译你,他们确实在你规定的相同环境下编译,我(VS 2008)。
我不相信Example::Three
,并Example::Four
应在标准C ++的编译一切,但我认为这是一个gcc的扩展,允许它。 Example::Five
不被编译。
您可以在源文件中初始化它们像struct声明打完,通常是:
const float Example::Three = 2000.0f;
const double Example::Four = 3000.0;
const string Example::Five = "Hello";
这是最便携的方式做到这一点,我会建议的方式做它,即使你的编译器可以让你在你的声明中定义Example::Three
和Example::Four
。
另一种选择是简单地从相同类型的静态函数返回值。
struct Example
{
//...
static double Four() { return = 3000.0; }
//...
};
#1和2是符合标准的。不幸的是,一些编译器根本不符合。这就是为什么,例如,升压设计师不得不引进像BOOST_STATIC_CONSTANT
恼人的宏来生成便携库。如果您不想定义.cpp文件不断,便携式解决方法是使用一个enum
。虽然,显然在这种情况下,你不知道该类型的担保,并且不能使用浮动。
在C ++ 98,只有静态常量的成员 整型可以初始化 在类,和初始化有 是常量表达式。这些 限制确保我们可以做 初始化在编译时。
请参阅在级成员初始化一>
§9.4.2静态数据成员
如果静态数据成员是常量积分或const枚举类型的,其在类德音响nition声明可以 指定一个恒定初始化其应是整数表达式(5.19)。在这种情况下,构件可以出现 在整型常量表达式。该成员仍应在命名空间范围定义去科幻如果在程序中使用和 命名空间范围去网络nition不得含有一个初始化。
在VS2008我得到以下错误:
1>.\Weapon Identification SystemDlg.cpp(223) : error C2864: 'Example::Three' : only static const integral data members can be initialized within a class
1>.\Weapon Identification SystemDlg.cpp(224) : error C2864: 'Example::Four' : only static const integral data members can be initialized within a class
1>.\Weapon Identification SystemDlg.cpp(225) : error C2864: 'Example::Five' : only static const integral data members can be initialized within a class
它吮吸,但我猜你只是如果你的编译器拒绝太不这样做......我不知道这是一个规范的事情,但我确定有人会纠正我......
重新浮点初始化时,C ++ 98规格有这样一段话(5.19):
浮动文本可以仅出现如果它们被转换为积分或枚举类型。
正如其他人已发现,C ++标准者禁用初始化静态const成员与浮点值。
至少据我了解,有一个非常简单的原因。有一种感觉(至少部分地对齐),一个实现应该被允许动态调整浮点精度,所以它可能不是直到落实知道会/从一个特定浮点产生精确的浮点值运行文字。事实上,这可能在执行过程中改变甚至有可能。
这个能力并在真实的硬件存在。只是举例,在Intel x86有一对情侣在浮点控制寄存器控制浮点计算的准确性位。默认情况下,计算是在80位长的双类型来完成的,并且仅四舍五入到像根据请求一个64位双或32位浮点。在寄存器这些位可以在执行过程中被修改,以便(例如)“1.23”在一个地方可能的变量初始化为一个值,而“1.23”,在程序的另一部分(精度已经被调节之后)可能会导致在(略)不同的值。
至少就我所知,这仍然是一种理论上的可能性,至少在最典型的机器。虽然英特尔硬件允许的FP精度动态调整,我不知道任何编译器(甚至不是英特尔的),试图翻译FP文字时(虽然英特尔的编译器至少支持80位长采取这样的调整考虑在内双型)。
正如其他人所指出的那样,你的编译器是在某些情况下破坏。但我从来没有真正理解比“标准是这么说的”其他它为什么不允许浮点类型的原因。目前似乎没有很好的技术原因。