C++中的const用法总结

const是修饰符,说明有只读特性。
首先明确以下代码:

int a=5;
const int a_const=a;//right
int b=a_const;//right
    
int * p=  &a_const;//error 
int * p=(int*) &a_const;//right
const int* p_const=&a;//right

说明只能从宽松到严格,反之不行。
const用法包括以下:

一.const变量

由于只读不能修改的特性,因此const变量必须初始化
const全局变量可以替换常量宏定义,比宏定义的直接替换更严格一些(见第三)。
const结构体变量,表示结构体中的任何数据域均不允许改变,且需要另外一个结构体变量进行初始化。

二.const类对象

不能改变任何成员变量的值以及不能调用任何非const成员函数(见第九)。

三.指向const变量的指针

该指针指向的变量是const的。
那么 编译器是如何判断只读呢?是通过指针的类型(const int *)还是指向变量的类型(const int)?

int a=5;
const int a_const=a;
    
int * p=  (int*)&a_const;
const int* p_const=&a;
    
*p=10;//right
*p_const=10;//error

从结果可以看出,如果指针类型是“const int*”即使其指向的内容是非const,也无法通过指针改变数据内容。反之,如果指针类型是普通的“int *”,即使其指向的变量是const,也可以修改这个指针指向的内容。因此,编译器是通过指针的类型来判断是否只读的。那么,一个新问题来了!!上述代码中的,*p=10执行后,a_const的值是多少?看下面代码:

const int volatile a_const=5;
int * p=  (int*)&a_const;
*p=10;
cout<<a_const<<endl;// 10
cout<<*p<<endl;//10
const int a_const=5;
int * p=  (int*)&a_const;
*p=10;
cout<<a_const<<endl;// 5
cout<<*p<<endl;//10

在本机上的结果如上所示。编译器会将const变量放在符号表中,直接从表中获的值,而不访问实际的内存。但是当在a_const前面加上volatile时,说明a_const是容易变化的,因此就修改了const值。 根据不同编译器的优化情况导致结果而不同(VC上,不管是否加violatile,都时直接从符号表中获取)。说明,const只是说明从道义上不会改变。
但是,我还发现了一个问题,上代码:

int a=5;
const int a_const=a;
int * p=  (int*)&a_const;
*p=10;
cout<<a_const<<endl;// 10
cout<<*p<<endl;//10

const int a_const=a;猜测是这一句,因为a是可变的,所以使得编译器认为a_const也是可变的,因此不会产生立即数。只是猜测,有机会再验证吧。
同时,如果把const int a_const作为全局变量时,

int a=5;
const int a_const=a;
int main()
{
    int * p=  (int*)&a_const;
    *p=10;
    cout<<a_const<<endl; //10
    cout<<*p<<endl; //10
}
const int a_const=5;
int main()
{
    int * p=  (int*)&a_const;
    *p=10;   //段错误
    cout<<a_const<<endl;
    cout<<*p<<endl;    
}

不管怎样,我们都可以使用const全局变量,来替代宏定义。根据上述可知,在实际执行中,会直接去查找符号表,因此不会产生一次变量的内存访问,和宏有相同的执行效率。同时,const全局变量可以通过编译器进行类型检查,来减少错误。

四.const指针

指针本身的地址值不能变,就是指针具体指向哪个变量是不能变的。

五.指向const变量的const指针

都不改变

六.const变量作为函数参数

在函数内部不能修改这个参数的值。不关心在函数外部是否是const。
但是,注意int*可以隐式的转换成const int*,反之,const int*不能隐式转化为int*。因此,

void func(int* param){
    cout<<*param<<endl;
}
int main()
{
    int a=5;
    const int p=5;
    func(&p);//error: invalid conversion from 'const int*' to 'int*'
}

七.const返回值

指的是函数的返回值是一个const变量
函数返回const返回值,主要用于函数返回const引用。对于返回引用的函数来说,我们不希望通过修改返回的引用来对原值进行修改,否则代码的健壮性太差。而通过将返回值写成const引用,就可以很好的解决。和下面代码一个道理:

int b=5;
const int &a=b;
a=10;//error assignment of read-only reference ?a?
int &a_=b;
a_=10; //right b=10

八.const成员变量

const成员变量必须初始化(在构造函数的初始化列表中),初始化后,不能修改
静态const成员变量需要在类外单独定义并初始化

类对象的构造过程:首先,开辟整个类对象的内存空间。根据类成员的情况,分配各个成员变量的内存空间,并通过构造函数的初始化列表进行初始化。最后,在执行构造函数中的代码

静态成员变量不属于类,不依附于任何实例化对象。因此,静态成员变量应该在任何实例化操作之前,就开辟好空间,又由于const成员变量必须初始化,因此在static const变量在定义时就完成初始化。

九.const成员函数

const成员函数不应该修改任何成员变量。
注:mutable关键字是为了突破const的。带有mutable修饰的成员变量,即使在const成员函数中也可以修改。
传给const成员函数的this指针,是指向const对象的const指针
而一般的非const成员函数,需要传入的this指针类型是指向一般对象的const指针。因此,需要将const int* const p 转换成int* const p才能实现调用非const成员函数,但是,很明显,由严格到宽松是不现实的。所以,const对象不能调用非const成员函数
那非const对象能调用const成员函数吗?
答案是能。因为非const对象表示其可变,既能访问const成员函数,也能访问非const成员函数。const对象只能访问const成员函数

总结

image.png

引用自:https://zhuanlan.zhihu.com/p/90720012

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352