为什么声明为类成员的const变量仍然可以修改?

时间:2014-06-15 02:31:40

标签: c++ c++11 initialization declaration

如果仍然可以重新分配已分配的const变量,那么它不是const?举个例子:

 struct ss
 {
     const int m = 1024;

     ss()
     {
     }

     ss(int m) : m(m)
     {
     }
 };



ss sa;
ss sb(-1);

cout << sa.m << endl;
cout << sb.m << endl; 

哇m毕竟不是常数!

> /* Ouput:
> 
> 1024
> -1
> 
> */

2 个答案:

答案 0 :(得分:11)

 ss(int m) : m(m)
 {
 }

这表示在初始化类ss时,使用参数m初始化其成员m。成员m确实无法修改,但可以像任何其他const对象一样进行初始化。请注意,如果我们改为

 ss(int m)
 {
     this->m = m;
 }

然后我们会遇到问题,因为ss::m需要初始化。如果ss::m是一个带有默认构造函数的类,那么在

 ss(FooClass m)
 {
     this->m = m;
 }

可以不显式初始化ss::m(因为它只是默认构造),但构造函数体中的行将被拒绝,因为它在已经修改ss::m之后会被修改已初始化。

编辑:哎呀,我不明白你原来的问题。

大括号或等号初始化,例如

const int m = 1024;

仅在 ctor-initializer 中未提及该成员时使用。换句话说,由于默认构造函数未显式初始化m,因此使用值1024。但ss::ss(int)会明确初始化m,因此会忽略大括号或等号初始化

答案 1 :(得分:5)

您的示例只处理不同的初始化模式,此处不会进行重新分配。您所看到的是构造函数初始值设定项列表优先于类成员初始值设定项的效果,我们可以从draft C++ standard部分12.6.2 初始化基数和成员段落< em> 9 说:

  

如果给定的非静态数据成员同时具有   brace-or-equal-initializer和mem-initializer,初始化   由mem-initializer指定执行,以及非静态数据   member的brace-or-equal-initializer被忽略。 [例子:给定

struct A {
int i = / some integer expression with side effects / ;
A(int arg) : i(arg) { }
// ...
};
     

A(int)构造函数只需将i初始化为arg的值,   并且在我的大括号初始化器中的副作用不会   地点。 - 例子]

正如Has the new C++11 member initialization feature at declaration made initialization lists obsolete?中所讨论的,这是一个有用的功能,因为它允许您默认成员变量,然后根据被调用的构造函数覆盖这些默认值。