struct A {
static const int a = 5;
struct B {
static const int b = a;
};
};
int main() {
return A::B::b;
}
以上代码编译。但是,如果你选择Scott Myers的Effective C ++书籍(第14页); 除声明外,我们还需要一个定义。 谁能解释为什么这是一个例外?
答案 0 :(得分:19)
C ++编译器允许静态const整数(仅限整数)在声明它们的位置指定其值。这是因为变量基本上不需要,并且仅存在于代码中(通常是编译出来的)。
其他变量类型(例如static const char *)通常不能在声明它们的地方定义,并且需要单独的定义。
对于更多解释,请注意,访问全局变量通常需要在较低级别的代码中进行地址引用。但是你的全局变量是一个整数,其大小通常在地址大小附近,并且编译器意识到它永远不会改变,那么为什么还要添加指针抽象?
答案 1 :(得分:19)
通过非常迂腐的规则,是的,您的代码需要该静态整数的定义。 但是根据实际规则,以及所有编译器实现的内容,因为C ++ 03的规则是如何实现的 - 不,你不需要定义。
这种静态常量整数的规则旨在允许您省略定义,如果仅在立即读取值的情况下使用整数,并且静态成员可以在常量表达式中使用。
在return语句中,会立即读取成员的值,因此如果仅使用它,则可以省略静态常量整数成员的定义。但是,以下情况需要定义:
struct A {
static const int a = 5;
struct B {
static const int b = a;
};
};
int main() {
int *p = &A::B::b;
}
这里没有读取任何值 - 而是取了它的地址。因此,C ++ 03标准的目的是您必须在某些实现文件中为成员提供如下所示的定义。
const int A::B::b;
请注意,C ++ 03标准中出现的实际规则表明,只有在常量表达式需要的情况下使用变量时才需要定义。但是,如果严格适用,该规则过于严格。它只允许你省略像数组维这样的情况的定义 - 但是在返回语句的情况下需要定义。相应的缺陷报告为here。
C ++ 0x的措辞已更新,包括该缺陷报告解析,并允许您的代码编写。
答案 2 :(得分:2)
但是,如果在没有“定义”静态consts的情况下尝试三元操作数,则会在GCC 4x中出现链接器错误:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795
因此,虽然像int k = A::CONSTVAL;
这样的结构在当前标准中是非法的,但它们是受支持的。但三元操作数不是。如果你得到我的漂移,有些操作员比其他操作员更平等:)
“松懈”规则太多了。如果你不想要惊喜,我建议你编写符合标准的代码。
答案 3 :(得分:0)
通常,大多数(和最近的)C ++编译器都允许使用静态const int
你很幸运,也许不是。尝试使用较旧的编译器,例如gcc 2.0,它会严重惩罚你的错误消息。