你所不知道的 const

1. const对象的初始化

const 常量是不可修改的,也就是说only read,例如

const int nBuffSize = 512;
nBuffSize = 0; //error 
就是因为const 常量不能修改,所以定义时必须初始化

2. const对象的文件局部性

默认在全局作用域中定义的非const变量可以在整个程序中访问,例如

//file1.c
int nCounter;

//file2.c
extern int nCounter;
++nCounter;

但是在全局作用域中声明的const变量是定义的文件局部变量,只能被该文件使用,不能被其他文件使用。可以通过指定const变量为extern,就可以在全局中使用,如下

//file1.c
extern const int nCounter = 1024;
//file2.c
extern int nCounter;

非const变量默认为extern,要使const变量能够在其他文件中访问,必须显示地指定它为extern

3. 指向const对象的指针和const指针

先看下面的例子

const int *p;
int * const p;

第一个就是指向的内容为const,而第二个是指针为const

另外要注意:不能使用void*指针保存const对象的地址,必须使用const void*,如下

const int nBuff = 42;
const void* pv1 = & nBuff;
void * pv2 = &nBuff;  //error 

4.const隐式转换

当使用非const对象初始化const对象的引用时,可以将非const对象转换为const对象,如下

	int nVala = 10;
	const int nValb = 0;
	const int &nValc = nVala;
	const int *pVald = &nValb;
当要使用非const变量初始化const变量,必须要将非const变量初始化,如下

int iVal = 123;
const int m = iVal;

5. 强制类型转换const_cast

const_cast就是隐式转换掉表达式的const性质,假设有函数string_copy,我们对其char*参数只读不写

	const char* pc_str = "hello world!";
	char* pc = string_copy(const_cast<char*>(pc_str));

6. const形参的复制

1)在调用函数的时候,如果函数使用非引用的非const形参,则可以传递const实参也可以额传递非const实参,如下:

	int func(int, int);  
	const int nVal1 = 3, nVal2 = 6;
	int nVal3 = 12, nVal4 = 13;
	int nResult1 = func(nVal1, nVal2); 
	int nResult2 = func(nVal3, nVal4);
传递的实参类型为const int的调用,因为初始化复制了形参的值,可用const对象初始化非const对象,反之亦然。

2)如果将形参定义为非引用的const类型,不可以改变实参的局部副本,由于实参仍是以副本的形式传递,因此传递给函数的既可以是const对象也可以是非const对象。利用const引用形参可以避免复制实参,因为对于大部分的类类型或者大型数组,复制的效率太低下了,使用引用形参可以直接访问实参对象,而无需复制它,如下

int GetSqListElem(const SqList &L, const ElemType data); //得到线性表中数据为data的第一个索引位置

第个形参可以避免复制结构体L,使用const引用可以避免复制,同时避免修改实参参值,第二个虽然使用了const 但是没有使用引用,所以还是会复制实参

7. const成员函数返回*this

在普通的非const成员函数中,this的类型是一个指向类类型的const指针,为什么指针是const?因为当前对象已经确定,改变指针的值就是改变指向的对象。在const成员函数中,this指针是一个指向const类类型的const指针,也就是说指针不能改变,同时指向的内容也不能改变,也就是说不能改变对象的成员和函数,只能获取成员的值或者函数等,如下:

/*注意const成员函数的*this返回值为const screen*/
const screen& screen::display(ostream& os) const 
{
	cout << "const:";
	do_display(os);	
	return *this;
}
注意这里返回的是*this,就是const screen

8. 基于const的重载

const对象只能使用const成员,非const对象可以使用任一成员。如下:

public:
		//重载函数
	screen& display(ostream& os); // 可以使用任何成员
	const screen& display(ostream& os) const; //只能使用const成员
private:
	void do_display(ostream& os) const;
如下调用
	string str = "abcdefg";
	screen myscreen(str, 0, 5); //栈上分配的空间
	const screen constscreen(str, 0, 4);

	myscreen.display(cout);
	constscreen.display(cout);
这里调试一下,就会发现const版本的就只会调用const函数

9. 用于类对象的const构造函数

构造函数不能声明为const,因为构造函数就是要初始化类,如果声明为const就无法初始化

public:
    sales_item(void) const;
这样编译的话就会出错

10. const static成员

一般,类的static成员,是不能在类的定义体中初始化,相反static数据成员通常在定义时初始化,整型const static数据成员就可以在类的定义体中进行初始化:

typedef double Money;
class account
{
public:
	account(){};
	~account(){};

	Money balance(){ return bal; }
	static double rate(){ return interestRate; }
	static void rate(double);
private:
	typedef long double Money;
	Money bal;
	static double interestRate;
	static const int period = 30;
	double daily_tbl[period];
};

const static数据成员在类的定义体中初始化时,该数据成员仍必须在类的定义体外进行定义,在类内部指定初始化值,成员的定义不必再指定初始值,如下

const int account::period;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值