C++关键字之const

const即constant的缩写,意为持久不变的.

1.通过const修饰来定义常量

在常量定义前加const,可以使定义的常量只读,不能修改.如:

int main(){
    const int a = 12;
    a = 13;//编译报错:表达式必须是可修改的左值
    cout<<a;
    return 0;
}

2.const修饰指针

const修饰指针有三种情况.

(1)const修饰指针

当以下面形式声明指针时,则为const修饰指针,声明的指针p为常量指针.

int main() {
    
    int a = 12;
    const int* p = &a;//p为常量指针
    return 0;
}

常量指针:指针指向的是常量.即指针的指向可以修改,但指针指向的值不能修改.

int main() {
    
    int a = 12;
    int b = 10;
    const int* p = &a;//p为常量指针
    *p = b;//错误,试图修改指向的值.编译报错:表达式必须为可修改的左值
    p = &b;//正确,修改指针的指向,可以通过编译
    return 0;
}

(2)const修饰常量

当以下面形式声明指针时,则为const修饰常量,声明的指针p为指针常量.

int main() {
    
    int a = 12;
    int* const p = &a;//p为指针常量
    return 0;
}

指针常量:指针本身为常量.即指针指向的值可以修改,但指针的指向不能修改.

int main() {
    
    int a = 12;
    int b = 10;
    int* const p = &a;//p为指针常量
    *p = b;//正确,修改指针指向的值,可以通过编译
    p = &b;//错误,试图修改指针的指向,报错:表达式必须为可修改的左值
    return 0;
}

(3)const既修饰指针,又修饰常量

当以下面形式声明指针时,则为const既修饰指针,又修饰常量.

int main() {
    
    int a = 12;
    const int* const p = &a;
    return 0;
}

指向的值和指针的指向都不能改变.

int main() {
    
    int a = 12;
    int b = 10;
    const int* const p = &a;//p为指针常量
    *p = b;//编译不通过
    p = &b;//编译不通过
    return 0;
}

(3)const修饰指针总结

image-20210906151455637.png

3.const修饰引用

const修饰引用的情况只有一种,即:

int main() {
    int a = 12;
    const int& r = a;
    int& const r = a;//这样写跟不加const没区别
    r = 10;//编译不通过,r为常量不能修改
    return 0;
}

当用const修饰引用时,可以直接赋右值给引用.

int main() {
    int& r = 10;//编译不通过,必须赋左值
    const int& const_r = 10;//编译通过
    //使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名
    //int temp = 10;
    //const int &ci = temp;
    return 0;
}

4.使用场景

(1)定义全局常量

类似于define宏定义,将不会变的常量进行定义,方便调用.如:

const double PI = 3.14159625;
int main(){
    return 0;
}

(2)修饰形参

当我们需要传递一个较大的对象给函数作为参数时,为了节省内存,可以将函数参数定义为指针或者引用类型,然后将对象的指针或引用传递给参数即可.为了防止函数中对形参进行修改(因为这样会影响到实参),一般将形参加上const修饰符,从而使其变为只读.如:

struct User {
    int uid;
    string pwd;
};
void user_print(const User& user) {
    user.uid = 300;//编译不通过
    cout << "uid: " << user.uid << endl;
    cout << "pwd: " << user.pwd << endl;
}
int main() {
    User user = { 316,"123456" };
    user_print(user);
    return 0;
}

5.面向对象中的const

(1)const修饰成员函数

  • const修饰的成员函数称为常函数
  • 常函数内不可以修改成员属性
  • 成员属性声明时加关键字mutable后,在常函数中依然可以修改
class A {
private:
    int a;
    mutable int b;
public:
    void show_A() const{
        a = 10;//无法通过编译
        b = 20;
    }
};

本质:每个成员函数都有一个隐藏的参数,即this指针,this指针的本质就是一个指向自身对象的一个指针常量(Type* const this),所以this指针的指向不会变,永远指向自己.给成员函数加const修饰相当于给this指针又加上了const修饰指向的值,即(const Type* const this),这样,this指针的指向不会变,指向的值也不允许改变.

(2)const修饰对象

  • 声明对象前加const称该对象为常对象
  • 常对象只能调用常函数,普通对象既可以调用普通成员函数,也可以调用常函数
  • 常对象不能修改属性
class A {
private:
    int a;
    mutable int b;
public:
    void show_A() const{
        
    }
    void show() {
        
    }
};
int main() {
    const A a;
    a.show_A();//正确
    a.show();//错误
    return 0;
}

6.const与define宏定义的区别

  • 作用阶段:define只在预处理阶段起作用,而const在编译和运行阶段起作用.因此,const可以进行调试而define不行;
  • 作用方式:define为简单的字符串替换,const有类型检查,因此const比define更安全,不易出错;
  • 存储方式:define只是进行展开,有多少地方使用,就替换多少次,它定义的宏常量在内存中有若干个备份;const定义的只读变量在程序运行过程中只有一份备份。所以const比define要节省内存.

结论:⚡const⚡与⚡define⚡相⚡比⚡,那⚡我⚡还⚡是⚡感⚡觉⚡我⚡们⚡const⚡牛⚡逼⚡

7.const_cast

const_cast用于去除const限定,但其目的并不是修改const修饰的变量(而且也修改不了)

使用场景举例:

我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数确实const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。如:

void fun(int* a) {
    //*a++;
    cout << *a;
}
void main(){
    const int constant = 12;
    int* p = const_cast<int*> (&constant);//通过const_cast去除const限定
    fun(p);
}

传统转换方式实现const_cast

const int constant = 12;
int* p = (int*)&constant;//直接通过显示转换,强转指针类型

详见:https://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html

参考文章:https://blog.csdn.net/weixin_38279101/article/details/112355990

https://blog.csdn.net/weibo1230123/article/details/81981384

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

推荐阅读更多精彩内容