C++ 类中的static, const, &引用类型变量的初始化的思考

参考:  https://blog.bccn.net/zpcdbc/15060

https://blog.csdn.net/cyqllfh/article/details/13295919

在以下三种情况下需要使用初始化成员列表:

一,需要初始化的数据成员是对象的情况;

二,需要初始化const修饰的类成员;

三,需要初始化引用&成员数据;

 

static const兼有static、const的双重特点,故不能初始化static、const数据成员的形式,自然不能拿来初始化static const。即不能直接初始化(当然不包括后面讲到的特例),也不能在构造函数中初始化(无论是在初始化列表还是在函数体中)。由于情况与前边十分类似,这里不再给出代码来举例说明。

 

既然如此,那就只好在类外初始化,形式同static。

再说明特殊情况, static const int型 和static const char型数据成员可以在类内初始化!

为什么存在int等整形特殊情况?个人认为最有说服力的答案是:

静态常量整型(int,short,long)数据成员,经常用来当作常量表达式constexpr使用,不在内部定义的话(类中就地初始化),则该常量表达式未定义,就不能使用了。比如用它作为数组的size,就不合适了。

C++11 非静态成员变量(常量),可以直接初始化,或者在初始化表中初始化。

C++11 中 初始化非静态成员变量(常量),可以看作赋给变量(常量)一个默认值。

===============================================================================

除此之外,本人补充一下:

static const int a=1;并不分配内存,编译时直接将a换成1,放到常量表中(关于常量表,本人不是很清楚,读者可以百度,有知道的欢迎告诉我),当然,若对a取地址,则在只读的常量区分配内存。所以,这和类声明不分配内存并不矛盾。至于为什么char型数据成员也可以,我想着应该与char的实现机制有关,char型可以转换成int型,毕竟我们知道字符可以以int型输出其ASSIC码值。不知道我的想法是否正确,欢迎高人批评指正。

 而至于为什么别的类型(比如float)不可以在类内初始化,是因为他们不能像int那样直接进行常量替换,而为什么不能直接进行常量替换。

-------------------------关于static const int可以在 声明时初始化的思考--------------------------

 《Effective C++》中文第三版P14,有这样一个例子:

 

class GamePlayer{
private:
	static const int NumTurns=5;//常量声明式
	int scores[NumTurns];//使用该常量
	...
};

         文中明确指出,NumTurns为声明式而非定义式。这与我们平时理解一个变量初始化赋值后即肯定被定义,这一观念相违背。而通过实验我们发现NumTurns确实未被定义,NumTurns仅仅完成声明,并在类编译过程中被5所替代。那么为什么会出现这么奇怪的现象呢?

       1、首先需要从const谈起。我们知道由const修饰的变量其对应的数值保持恒定不变。类的成员变量,如果由const 修饰,能且只能在构造函数的初始化列表中完成初始化。例:

 

class A
{
	public:	
		A():a(1){}
	private:
		const a;
};

 

      原因在于const成员变量,它属于类生成的对象,在每一个对象中都包含了一个相应的const成员变量。在建立对象的过程中完成const成员变量的初始化。而必须在初始化列表中完成初始化则是由于当const成员变量出现在构造函数体内时默认完成的是赋值操作。这与const成员变量必须保持相应的值不变相矛盾。

 

       2、与const成员变量相对应的是static成员变量。当static修饰成员变量的时候,表示相应的成员变量直接属于类本身,为类生成的所有对象共有。我们在统计对象的数量时,可以通过使用static成员变量来实现。同时static相当于一个范围限定符,它限定所修饰的成员变量为该文件所特有。

         类的static成员变量,在类体外完成初始化,例:

 

class B
{
	public:
		B(){}
	private:
		static int a;
};
int B::a=2;//在类外初始化时,省略掉static,避免与其他全局static变量混淆

 

         3、既然已经有了const、static成员变量,那么static const 成员变量的产生也就顺理成章了。static const成员变量可以认为是该文件一个专属的成员变量,它属于类本身,并为所有对象、友元函数所共享。

         static const成员变量初始化方式,与static成员变量相同,例:

 

class C
{
	public:
		C(){}
	private:
		static const string s;
};
const string C::s="hello world";//在类体外初始化,同样省略掉static

 

         4、static const int NumTurns=5

         新的C++编译器对此的解释为:当一个变量为class专属的const常量,同时为整型(包括int、char、bool等),可以在声明时完成初始化操作。static const 整型变量的定义同普通的static const 成员变量,还需要在类体外完成初始化。

         回来最初的例子中:

 

class GamePlayer{
	private:
		static const int NumTurns=5;//常量声明式
		int scores[NumTurns];
		...
};
const int GamePlayer::NumTurns;//完成NumTurns的定义,无此句依然可以通过编译

 

 

         在过去的C++编译器中,是不允许在声明时初始化,现在几乎所有的编译器都支持这一行为。其背后的原因主要如下:
         1)类内的static const 整型变量,一般是为了完成对其他成员变量初始化操作。如本例中scores[]数组需要预先指定数组的大小,这样才能通过编译。同时,通过static const修饰的整型变量由于未定义,在编译的过程中直接被初始化的值所替代,这样可以简化内存。

         2)为了更好的替代C中的宏。C语言中的宏在预编译阶段即完成替换,static const 整型成员变量可以类似于宏那样工作,同时限定了作用域。从这方面来说,是一个更好的宏的替代方案。

         3)契合C++的设计理念。对于同一种功能要求,C++总能提供不同的解决方法以供使用。static const int 与enum遥相呼应,enum也是使用一个记号标明对应的值。使用enum的情况如下:

 

class GamePlayer{
	private:
		enum {NumTurns=5};//"the enum hack"——令NumTurns 成为5的一个记号名称
		int scores[NumTurns];
	...
};

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值