C++ const用法详解

本文深入解析C++中const的定义、赋值、引用、指针及类中常量函数的用法,包括底层const与顶层const的概念,以及如何正确理解和应用const以避免常见错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const可以用来定义常量。

const写在数据类型前或后是等价的,如下两种写法是等价的。

const int a=10;
int const b=20;

常量将不能被修改,因此在定义时必须初始化。

以下写法将不能通过编译。

const int a;

const更多复杂的用法体现在它和引用或指针的组合中。

int a=10;
int &b=a;//普通引用
const int &c=a;//常量引用,将不能通过引用修改变量


如果通过c来修改a将出错。

以下代码第四行将报错。

int a=10;
int &b=a;//普通引用
const int &c=a;//常量引用,将不能通过引用修改变量
c=5;


指针更加特殊。指针本身是一个对象,它指向的也是一个对象。因此const放在不同位置将有修饰不同的作用。


如果const修饰指针,则该指针将不能再指向其它对象,即常量指针。

以下是常量指针,它可以修改对象的值但是不能更换指向的对象。去掉注释部分将报错。

int a=10,b=20;
int *const xp=&a;
*xp=5;
//xp=&b;

如果const修饰的是指向的对象,则不能通过该指针修改它指向的对象,即指向常量对象的指针。

以下是指向常量对象的指针,它可以更换指向的对象但不能修改该对象的值。去掉注释部分将报错。

int a=10,b=20;
const int *xp=&a;
//*xp=5;
xp=&b;


以上两种的定义的区别要看const在*前还是后。在*前就是指向常量对象的指针,在*后就是常量指针。


如果const既修饰指针也修饰指向的对象,它将是指向常量对象的常量指针。既不能更换指向的对象,也不能修改指向对象的值。

int a=10,b=20;
const int *const xp=&a;
//*xp=5;
//xp=&b;


const可以用来定义常量,保证对象不被修改。于是在对象赋值时就出现问题了。

对于普通变量,这里没有问题,因为赋值操作是完成一次拷贝,拷贝完成后两个对象就没有任何关系了。

所以,以下两种代码都可以通过。

int a=10;
const int b=a;

const int a=10;
int b=a;

在以上代码中a和b的修改都不会影响到对方。

所以得出结论如果赋值运算符左侧对象是普通对象(非引用和非指针),我们就不用管右侧对象是否有const了,因为拷贝完成以后两个对象已经完全独立了。

但是如果左侧是引用或指针就不一样了,因为对他们完成赋值以后,他们还是跟原对象有关联的。试想,如果赋值右侧是一个const int,而左侧是int &,如果我们可以通过该引用来修改原常量对象,这将违背const的规则。事实上,c++将拒绝通过这种行为。

即如下代码是无法通过编译的。

const int a=10;
int &b=a;

把引用也改成const就可以了。

const int a=10;
const int &b=a;


同样,如果赋值右侧是非const对象,左侧是有const修饰,这将不会有任何问题,只是不能通过引用修改原对象而已,不会违背const的规则。

int a=10;
const int &b=a;

对于普通引用,它绑定的对象不能是常量,因此以下代码是错误。

int &a=10;

而对于常量引用,它绑定的对象可以是变量也可以是常量,以下代码是对的。

const int &a=10;

以上规则可以扩展至指针。

普通指针将不能指向常量对象,以下代码是错的。

const int a=10;
int *p=&a;
正确写法:

const int a=10;
const int *p=&a;
注意上面这是指向常量对象的指针,而非常量指针。常量指针不强调指向对象是否常量,因此下面的代码不能通过编译。

const int a=10;
int *const p=&a;

通过上面的一些例子,我们隐约可以感受到一丝的规律。如果const的修饰作用将涉及另一个对象(如果const修饰引用,修饰指针指向的对象)它就会有问题,否则如果只关系自己(如const修饰普通变量,修饰指针)那就没问题。在《c++ primer》一书中,作者将前者称为底层const,后者称为顶层const。

顶层const:

const int a=10;
int b=1;
int *const xp=&b;
int *yp=xp;
显然,普通的常量对象、常量指针,这里的const都是顶层const。仅被顶层const修饰的对象在赋值时会去掉const属性,因此它可被赋值给常量或非常量对象。如上第四行。

底层const:

int a=10;
const int *xp=&a;
const int *yp=xp;

const int b=1;
const int &q=b;

显然,常量引用、指向常量对象的指针,这里的const都是底层const。仅被底层const修饰的对象在赋值的时候const属性将被保留,因此它仅可被赋值给具有底层const的对象。如上第三和第六行。



如果理解了底层const和顶层const,大部分和const有关的问题就可以解决了。


下面我们用const的规则来解释一下c++中class中的常量函数。

众所周知,类的常量对象只能调用常量成员函数,不能调用非常量成员函数。

为什么呢?

实际上对象调用成员函数是通过this指针实现的。

this默认是一个常量指针,即永远指向该对象,这不会有问题,我们不能更换this指向的对象。调用该函数的this指针是一个常量指针,它有顶层const但没有底层const,因此对于常量对象是不能绑定到该this指针上的。所以常量对象不能调用非常量成员函数。

如果你在成员函数后面加一个const,即将其定义为常量成员函数,将意味着调用该函数的this是一个指向常量对象的常量指针。调用的时候自然要传参数啦,无论该对象是常量还是非常量都可以传给该this指针,因此常量对于常量成员函数,常量或非常量对象都可以调用。












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值