在C ++ Primer 4th 12.6.2 中,建议重新声明类外的const静态变量。
但是,下面的代码在gcc 4.6.3中传递。
#include <iostream>
using namespace std;
class X {
public:
const static int a = 1;
};
// const int X::a;
int main() {
X x;
cout << x.a << endl;
return 0;
}
我们应该重新申请吗?
PS:
根据 Potatoswatter 的建议,我添加了一个使用const静态成员作为参考的函数:
const int X::a;
void test(const int& a) {
cout << a << endl;
}
int main() {
X x;
test(X::a);
return 0;
}
如果我们在课程const int X::a
之外不包含X
,则会产生如下错误
undefined reference to 'X::a'
最好在类外部定义是否为const static。
答案 0 :(得分:3)
不,您不需要重新声明它,因为您已经声明并在单行中定义它:
const static int a = 1;
但是,对于static
数据成员(包括const static
),如果您只在类中提供声明。您必须在命名空间范围内的类声明之外定义静态成员。 For example:
class X
{
public:
static int i; // declaration
};
int X::i = 0; // definition outside class declaration
答案 1 :(得分:2)
来自http://en.cppreference.com/w/cpp/language/static:
常量静态成员
如果将整数或枚举类型的静态数据成员声明为const(而不是volatile),则可以使用大括号内定义的大括号括号或大小来初始化它。在这种情况下,不需要定义:
编译器的行为符合预期。没有足够的背景,很难判断“The C ++ Primer”的推荐。
答案 2 :(得分:2)
const static
成员的规则有例外:
对于static constexpr
成员,类型限制被删除(或替换为constexpr
的类型限制),并且必须是类内声明中的初始值设定项。
在任何一种情况下,声明都不被认为是一个定义,尽管有一个初始化器,因此该对象在类声明(因此定义)之前不会获得地址。对于模板的成员,可以在每个翻译单元(TU)中完成,对于非模板类的成员,它必须仅在一个TU中完成。
尽管您的示例是编译的,但实践通常不具有可伸缩性,因为此类变量无法传递给通用的传递引用函数,包括完美转发。这本书的建议很好。
标准参考:[class.static.data]§9.4.2/ 3。