为什么可以';类中有一个非整型静态常量成员吗? 我注意到C++将不编译如下: class No_Good { static double const d = 1.0; };
但是,它允许将double更改为int、unsigned或任何整数类型:为什么可以';类中有一个非整型静态常量成员吗? 我注意到C++将不编译如下: class No_Good { static double const d = 1.0; };,c++,C++,但是,它允许将double更改为int、unsigned或任何整数类型: class Happy_Times { static unsigned const u = 1; }; 我的解决方案是将其改为: class Now_Good { static double d() { return 1.0; } }; 并认为编译器将足够智能,可以在必要时内联。。。但这让我很好奇 为什么C++设计器允许静态const一个int或un签署,而不是一个双?< /p> 编辑:我正在Windows X
class Happy_Times {
static unsigned const u = 1;
};
我的解决方案是将其改为:
class Now_Good {
static double d() { return 1.0; }
};
并认为编译器将足够智能,可以在必要时内联。。。但这让我很好奇
<>为什么C++设计器允许静态const一个int或un签署,而不是一个双?< /p>
编辑:我正在Windows XP上使用visual studio 7.1(.net 2003)
编辑2:
问题已经回答,但为了完成,我看到的错误是:
error C2864: 'd' : only const static integral data members can be initialized inside a class or struct
我不知道为什么它会处理与int不同的double。我以为我以前用过那种形式。以下是另一种解决方法:
class Now_Better
{
static double const d;
};
在.cpp文件中:
double const Now_Better::d = 1.0;
问题是,对于整数,编译器通常不必为常量创建内存地址。它在运行时不存在,它的每次使用都会内联到周围的代码中。它仍然可以决定给它一个内存位置——如果它的地址曾经被占用(或者如果它通过const引用传递给函数),那么它必须这样做。为了给它一个地址,它需要在一些翻译单元中定义。在这种情况下,您需要将声明与定义分开,否则它将在多个翻译单元中定义 使用无优化(
-O0
)的g++时,它会自动内联常量整型变量,但不会内联常量双精度值。在更高的优化级别(例如,-O1
)下,它将常量加倍内联。因此,以下代码在-O1
处编译,而不是在-O0
处编译:
// File a.h
class X
{
public:
static const double d = 1.0;
};
void foo(void);
// File a.cc
#include <stdio.h>
#include "a.h"
int main(void)
{
foo();
printf("%g\n", X::d);
return 0;
}
// File b.cc
#include <stdio.h>
#include "a.h"
void foo(void)
{
printf("foo: %g\n", X::d);
}
为了实现最大的可移植性,您应该在头文件中声明常量,并在某个源文件中定义它们一次。如果没有优化,这不会影响性能,因为您无论如何都没有进行优化,但是如果启用优化,这可能会影响性能,因为编译器无法再将这些常量内联到其他源文件中,除非启用“整个程序优化”。我看不出技术原因
struct type {
static const double value = 3.14;
};
这是禁止的。任何情况下,您发现它的工作原理都是由于非可移植的实现定义的特性。它们似乎也只有有限的用途。对于在类定义中初始化的整型常量,可以使用它们并将它们作为非类型参数传递给模板,还可以将它们用作数组维度的大小。但对于浮点常量不能这样做。允许浮点模板参数将带来它自己的一套规则,这并不值得费心
但是,下一个C++版本将允许使用<代码> CONTXPRP</代码>:
struct type {
static constexpr double value = 3.14;
static constexpr double value_as_function() { return 3.14; }
};
并将使type::value
成为常量表达式。同时,您最好的选择是遵循std::numeric\u limits
:
struct type {
static double value() { return 3.14; }
};
它不会返回常量表达式(编译时不知道值),但这只关系到理论,因为实际值无论如何都会内联。见提案。它包含
4.4
浮点常量表达式
传统上,评估
温度下的浮点常数表达式
编译时间是一个棘手的问题。对于
我们建议统一性和普遍性
允许数据的常量表达式
浮点数类型,初始化为
任何浮点常数
表达。这也会增加
与C99的兼容性[ISO99,§6.6]
允许
[#5]计算结果为
常量在几个方面都是必需的
上下文。如果一个floating表达式是
在翻译环境中评估-
环境、算法精度和性能
范围应至少与
正在对表达进行评估
执行环境
<>这并没有给出一个理论,但这里是Stroustrup在C++编程语言第三版中所说的: 10.4.6.2构件常数 也可以初始化 静态积分常数构件法 添加常量表达式 其成员声明的初始值设定项。 例如:
class Curious {
static const int c1 = 7; // ok, but remember definition
static int c2 = 11; // error: not const
const int c3 = 13; // error: not static
static const int c4 = f(17); // error: in-class initializer not constant
static const float c5 = 7.0; // error: in-class not integral
// ...
};
class X {
enum { c1 = 7, c2 = 11, c3 = 13, c4 = 17 };
// ...
};
但是,必须(唯一)定义已初始化的成员
在某个地方,初始值设定项可能不存在
请重复:
const int Curious::c1; // necessary, but don't repeat initializer here
我认为这是个错误。当你需要一个符号常量时
在类声明中,使用
枚举器(4.8、14.4.6、15.3)。对于
例如:
class X {
enum { c1 = 7, c2 = 11, c3 = 13, c4 = 17 };
// ...
};
这样,其他地方就不需要成员定义,您也不需要
试图声明变量,
浮点数等
在第C.5节(常量表达式)的附录C(技术细节)中,Stroustrup对“常量表达式”有这样的说法:
在数组边界(5.2)、大小写标签(6.3.2)等位置,
枚举数(4.8)和C++的初始化器需要
恒定表达式。常量表达式的计算结果为
积分或枚举常数。这样的表达
由文字(4.3.1、4.4.1、4.5.1)组成,
枚举数(4.8)和由初始化的常量
常量表达式。在模板中,是一个整数模板
也可以使用参数(C.13.3)。浮动文字(4.5.1)
仅当显式转换为整数时才能使用
类型。函数、类对象、指针和引用
可以用作sizeof的操作数
仅限操作员(6.2)
直觉上,常量表达式是简单的表达式
可以在程序运行之前由编译器对其进行评估
已链接(9.1)并开始运行
请注意,他几乎忽略了浮点,因为他能够在“常量表达式”中使用。我怀疑浮点被排除在这些类型的常量表达式之外,仅仅是因为它们不够“简单”。以下是我基于Stroustrup关于类内定义的声明的理解 类通常在头中声明