在C++ 11之前,我们只能对整数或枚举类型的静态const成员执行类内初始化.Stroustrup在他的C++ FAQ中讨论了这个问题,给出了以下示例:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
Run Code Online (Sandbox Code Playgroud)
以下推理:
那么为什么存在这些不方便的限制呢?类通常在头文件中声明,并且头文件通常包含在许多翻译单元中.但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏.
但是,C++ 11放宽了这些限制,允许非静态成员的类内初始化(§12.6.2/ 8):
在非委托构造函数中,如果给定的非静态数据成员或基类未由mem-initializer-id指定(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer)然后,实体不是抽象类(10.4)的虚基类
- 如果实体是具有大括号或等于初始值的非静态数据成员,则按照8.5中的规定初始化该实体;
- 否则,如果实体是变体成员(9.5),则不执行初始化;
- 否则,实体默认初始化(8.5).
第9.4.2节还允许非const静态成员的类内初始化,如果它们用说明constexpr符标记的话.
那么我们在C++ 03中受到限制的原因究竟发生了什么?我们只是简单地接受"复杂的链接器规则"或者是否有其他改变使得这更容易实现?
我试图定义一个这样的公共静态变量:
public :
static int j=0; //or any other value too
Run Code Online (Sandbox Code Playgroud)
我在这一行得到了一个编译错误:ISO C++禁止非const静态成员`j'的类内初始化.
为什么在C++中不允许这样做?
为什么允许const成员初始化?
这是否意味着C++中的静态变量没有像C一样用0初始化?
谢谢 !
在课堂里:
class foo
{
public:
static int bar; //declaration of static data member
};
int foo::bar = 0; //definition of data member
Run Code Online (Sandbox Code Playgroud)
我们必须明确定义静态变量,否则会产生一个
undefined reference to 'foo::bar'
我的问题是:
请注意,这与先前提出的问题不重复undefined reference to static variable.这个问题打算问一下静态变量的明确定义背后的原因.
Scott Meyers 在 Effective Modern C++, Item 30 page 210 中写道,有
无需
static const在类中定义完整的数据成员;仅声明就足够了,
那么示例代码是
class Widget {
public:
static const std::size_t MinVals = 28; // MinVals' declaration;
...
};
... // no defn. for MinVals
std::vector<int> widgetData;
widgetData.reserve(Widget::MinVals); // use of MinVals
Run Code Online (Sandbox Code Playgroud)
我确信这static const std::size_t MinVals = 28;既是声明又是定义,因为它给了一个值MinVals,但评论似乎声称这只是一个声明;第二条评论实际上声称没有定义。代码后面的文字,确实是读
MinVals缺乏定义。
这证实这static const std::size_t MinVals = 28;不是一个定义,所以我有点困惑。
cppreference对我帮助不大(我的粗斜体):
如果声明
static了整型或枚举类型的数据成员(而不是),则可以使用初始化器对其进行初始化,其中每个表达式都是常量表达式,就在类定义中:constvolatileRun Code Online (Sandbox Code Playgroud)struct X { const static int …
我知道非常量静态变量需要在类定义之外进行初始化,但有没有理由呢?
class A {
static int x = 0 // compile error;
static int y;
};
int A::y = 0; // fine
Run Code Online (Sandbox Code Playgroud) 我知道只有静态,const和int/enum(pre c ++ 11)的数据成员才能在类声明中初始化."所有其他静态数据成员必须在全局命名空间范围内定义(即在类定义的主体之外),并且只能在这些定义中初始化".
为什么不能在类定义中初始化其他静态数据成员?这是被禁止的具体原因吗?
如果数据成员特定于该类,为什么它们在全局命名空间范围内声明,而不是与其类相关的某些范围?
因此,我知道在C ++中,如果静态成员是const文字类型,则可以在类内部对其进行初始化,如下所示:
class test{
public:
static constexpr int stc = 1;
private:
int a = 0;
int b = 0;
int c = 0;
};
Run Code Online (Sandbox Code Playgroud)
静态constexpr变量stc可以用在编译器可以直接替换成员值的地方,即
int main () {int array[test::stc];}
Run Code Online (Sandbox Code Playgroud)
但是,如果在不能由编译器直接替换值的上下文中使用:
int main() { const int &cs = test::stc; }
Run Code Online (Sandbox Code Playgroud)
然后编译器(c)生成一个错误
c++ -std=c++11 -pedantic t.cpp -o t
Undefined symbols for architecture x86_64:
"test::stc", referenced from:
_main in t-a8ee2a.o
ld: symbol(s) not found for architecture x86_64
Run Code Online (Sandbox Code Playgroud)
除非静态成员是在类外部定义的,例如:
constexpr int test::stc;
为什么会这样呢?