C语言深度解剖---const篇

1、const是constant的缩写,是恒定不变的意思,也翻译为常量常数等,很不幸,正是因为这一点,很多人都认为被const修饰的是常量,这是不精确的,精确的说应该是只读的变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。

const推出的初始目的,正是为了取代编译指令,消除他的缺点,同时集成他的优点,(define不是关键字哦!!)

const修饰的只读变量必须在定义的同时初始化。

case后面只能是常量或常量表达式,而不能是const修饰的只读变量。

const 修饰的只读变量不能用来作为定义数组的维数, 
也不能放在case 关键字后面。 


2、节省空间,避免不必要的内存分配,同时提高效率

编译器通常不为普通const只读变量分配内存空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。

例如:

#define M 3;    //宏常量

const int N=5;       //此时并未将N放入内存中

………………

int i=N; //此时为N分配内存,以后不再分配!

int I=M;  //预编译期间进行宏替换,分配内存

int j=N;   //没有内存分配

int J=M     //再进行宏替换,又一次分配内存。

const 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define 
一样给出的是立即数,所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为 
它是全局的只读变量,存放在静态区),而#define 定义的宏常量在内存中有若干个拷贝。 
#define 宏是在预编译阶段进行替换,而const 修饰的只读变量是在编译的时候确定其值。 
#define 宏没有类型,而const 修饰的只读变量具有特定的类型。 




3、const修饰指针

 const int *p;  // p 可变,p 指向的对象不可变 
       int const *p; // p 可变,p 指向的对象不可变 
       int *const p; // p 不可变,p 指向的对象可变 
       const int *const p; //指针p 和p 指向的对象都不可变 

    先忽略类型名(编译器解析的时候也是忽略类型名),我们看const 离哪个近。“近水楼 
台先得月”,离谁近就修饰谁。 

    const int  *p;  //const 修饰*p,p 是指针,*p 是指针指向的对象,不可变 
    int const *p; //const 修饰*p,p 是指针,*p 是指针指向的对象,不可变 
    int *const p; //const 修饰p ,p 不可变,p 指向的对象可变 
    const int  *const p; //前一个const 修饰*p,后一个const 修饰p ,指针p 和p      指向的对象 
    都不可变 



4、const修饰函数的参数

 const 修饰符也可以修饰函数的参数,当不希望这个参数值被函数体内意外改变时使 
     用。例如: 
     void Fun(const int i); 
     告诉编译器i 在函数体中的不能改变,从而防止了使用者的一些无意的或错误的修改。 


5、const修饰函数的返回值

const 修饰符也可以修饰函数的返回值,返回值不可被改变。例如: 
     const int Fun (void); 


在另一连接文件中引用const 只读变量: 
    extern const int i; //正确的声明 
    extern const int j=10; //错误!只读变量的值不能改变。 



一 const与指针

1  指针常量 

int*const ptr

指针常量,即不可以将ptr修改为指向内存中另一处的地址,但可以用它来改变它所指向的地址处的数据内容。

//const.cpp
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	int temp = 4;
	cout << temp << endl;

	//ptr被const修饰 定义时必须初始化
	int *const ptr = &temp;
	*ptr = 5;
	cout << temp << endl;

	return 0;
}


程序运行截图:

 

2 常量指针

const int *ptr;    (常量指针的另一种写法int const *ptr)

常量指针,即可以将ptr修改为指向内存中另一处的地址,但不可以用它来改变它所指向的地址处的数据内容。

//const.cpp
#include <iostream>
#include <cstring>
using namespace std;

int main()
{

	int temp1 = 4;
	int temp2 = 5;

	const int *ptr;
	ptr = &temp1;
	cout << "*ptr:" << *ptr << endl;

	ptr = &temp2;
	cout << "*ptr:" << *ptr << endl;

	return 0;
}


 

程序运行截图:

 

指向const常量的const指针

const int *const ptr;   (另一种写法int const *const ptr

指向const常量的const指针,即ptr所指向的内存地址和所指向的地址处的数据内容都不能被修改

 

PSconst离谁比较近,则谁的值不能被改变

 

 

二  const与函数

1 const修饰函数的参数

const使该参数在函数中不能被改变

void copy(char *strDes, const char *strsrc)

strsrc指针所指向的值在copy函数中不能被改变,如果意外的改动该指针,编译器会报错

 

注意:

不用将“值传递”的方式(void copy(int x, in y))加const修饰,因为函数会自动产生临时变量用于复制该参数,参数本来就不需要保护。

 

2 const修饰函数的返回值

const int* add(int x, int y);

add函数的返回值(即指针)的内容不能被修改,该返回值只能被赋值给加const修饰的同类型指针

const int *p = add(3, 5);

 

注意:

如果函数返回值是“值传递方式”(int add(int x, int y),由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有意义。

 

3 const成员函数

任何不会修改类的数据成员(即函数中的变量)的函数都应该声明为const类型。在编写const成员函数时,如果不小心修改了数据成员,或者调用了其他非const成员函数,编译器会报错,这种做法将大大提高程序的健壮性。

  1. //test.cpp   
  2. class test  
  3. {  
  4. public:  
  5.     void set(int);  
  6.     //const成员函数   
  7.     int get()const;          
  8. private:  
  9.     int value;  
  10. };  
  11.   
  12. int test::get()const  
  13. {  
  14.     //编译错误 修改数据成员value   
  15.     ++value;  
  16.     //编译错误 调用了非const函数   
  17.     set(5);  
  18.     return value;  
  19. }  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值