深入解析 const 关键字:指针、参数、返回值和类成员函数

news2024/12/23 20:56:59

文章目录

  • const 关键字的理解
  • 一、 修饰普通类型的变量
  • 二、const 修饰指针变量
  • 三、const 作参数传递 和 函数返回值
    • (1)const 修饰函数参数
    • (2)const 修饰函数返回值
  • 四、const修饰类成员函数
  • 结尾

const 关键字的理解

const 在 C++ 中是用来修饰内置类型变量自定义对象成员函数返回值函数参数

C++中, const允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。

使用const有以下好处:

  1. 编译器的静态检查:const 可以让编译器在编译时进行静态检查,确保不会对被声明为 const 的值进行修改。如果尝试修改 const 值,编译器将产生错误或警告。

  2. 代码可读性和维护性:使用 const 可以清晰地表达代码的语义,指出某个值不会被修改。可以提高代码的可读性,并且在维护代码时能够更好地理解和推理代码的含义。

  3. 防止意外修改:通过使用 const,可以避免在代码中意外地修改某个值。特别是当多人协作开发或者代码规模较大时,const 可以起到约束和保护的作用,防止错误的修改。

  4. 优化机会:const 还给编译器提供了一些优化机会,因为编译器知道 const 值不会被修改,可以进行一些相关的优化操作,提高程序的执行效率。

👇下面我们看const 关键字的使用👇


一、 修饰普通类型的变量

观察下面的代码:

const int a = 10;
int b = a; // 正常赋值
a = 20; // 错误,不能给常量赋值

当使用const修饰普通类型的变量a时该变量a会被编译器看成常量,而对常量赋值是违法的。

当我们写出如下的代码时,会发生一些出乎意料的情况:

在这里插入图片描述

我们发现,尽管在监视中a的值为20,但最终输出结果依然为10。

这是因为 编译器对常量的优化处理将常量 a 存储在只读内存区域,并且优化后的指令可能直接使用常量的值。虽然通过指针修改了数据,但是由于常量 a 是不可修改的,所以它的值仍然保持着 10。


上面的例子告诉我们,在c++中,尽量不要修改const修饰的变量。
但我们可以使用volatile 关键字,即下面的写法:

volatile const int a = 10;

当执行上面的代码时,最后结果会输出 “a的值为:20”

这是因为 volatile 关键字告诉编译器,这个变量的值可能会被意外地修改,因此每次使用这个变量时都要从内存中读取,而不是使用已经存在的寄存器中的值。如果没有使用
volatile,编译器可能会对这个变量进行一些优化,例如缓存这个变量的值,这样就无法保证每次使用这个变量时都是最新的值。


二、const 修饰指针变量

const 修饰指针变量有三种情况:

① const 修饰指针指向的内容,则内容为不可变量。
② const 修饰指针,指针为不可变量。
③ const 同时修饰指针和指针指向的内容,指针和指针指向的内容都为不可变量。


对于 ①:

const修饰的常量指针:指针本身是一个常量,不能修改指向的地址,但可以修改指向地址所存储的值。

// 理解为: const在int*前,所以
int a = 10, b = 20;
const int* ptr = &a;

// 修改指向地址所存储的值是合法的
*ptr = 20; // 错误,编译器会报错

// 修改指向的地址是不合法的
ptr = &b; // 合法,可以修改指针指向的地址

对于②:

const修饰的指针常量:指针指向的是一个常量,不能通过指针修改所指向地址处的值,但可以修改指针指向的地址。

int a = 10, b = 20;
int* const ptr = &a;

// 修改指向地址所存储的值是合法的
*ptr = 20; // 合法,可以修改指向地址处的值

// 修改指针指向的地址是不合法的
ptr = &b; // 错误,编译器会报错

对于③:

const同时修饰指针和常量:既不能修改指针本身,也不能通过指针修改所指向地址处的值。

int a = 10, b = 20;
const int* const ptr = &a;

// 修改指向地址所存储的值是不合法的
*ptr = 20; // 错误,编译器会报错

// 修改指针指向的地址是不合法的
ptr = &b; // 错误,编译器会报错

三、const 作参数传递 和 函数返回值

(1)const 修饰函数参数

const 修饰 函数参数有以下三种情况:

  1. const修饰的值传递参数
void func(const int num) {
    // 不能修改num的值
    // ...
}

在这种情况下,形参 num 被声明为常量,函数内部不允许修改它的值。


  1. const修饰的指针传递参数
void func(const int* ptr) {
    // 不能修改ptr所指向地址处的值
    // ...
}

这里 ptr 是一个指向常量整数的指针,函数内部不能通过指针修改所指向地址处的值,但可以修改指针本身。


  1. const修饰的引用传递参数
void func(const int& ref) {
    // 不能修改ref所引用的值
    // ...
}

在这种情况下,引用 ref 被声明为常量,函数内部不允许修改它所引用的值。


(2)const 修饰函数返回值

const 修饰返回值一样有下面三种情况:

  1. const 修饰返回值为常量:
const int func() {
    // ...
    return 10;
}

在这种情况下,函数 func() 的返回值被声明为常量,外部代码不能修改返回值。


  1. const 修饰返回指针类型的函数
int* const func() {
    // ...
    static int num = 10;
    return #
}

这里 int* const 表示返回值是一个指向整数的常量指针。使用 const 修饰的指针表示指针本身的值是常量,外部代码不能修改指针指向的地址。但可以通过指针修改所指向地址处的值。


  1. const 修饰返回引用类型的函数
const int& func() {
    // ...
    static int num = 10;
    return num;
}

在这种情况下,返回值是一个指向整数的常量引用。使用 const 修饰的引用表示外部代码不能通过引用修改其所引用的对象。


四、const修饰类成员函数

const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值,如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为 const 成员函数。

注意:const 关键字不能与 static 关键字同时使用,因为 static 关键字修饰静态成员函数,静态成员函数不含有 this 指针,即不能实例化,const 成员函数必须具体到某一实例。


有下面两种类型:

  1. const 修饰返回引用类型的函数
class MyClass {
public:
    void func() const {
        // ...
    }
};

在这种情况下,成员函数 fnc() 被声明为 const 成员函数。const 成员函数表示该函数不会修改类的成员变量。

在 const 成员函数中,不能修改非静态成员变量(除非是 mutable 修饰的成员变量),也不能调用非 const 的成员函数。


  1. const 修饰返回值为常量的成员函数
class MyClass {
public:
    int getValue() const {
        // ...
        return value;
    }
private:
    int value;
};

在这种情况下,成员函数 getValue() 被声明为 const 成员函数,并且返回值的类型是 const。这表明该成员函数不会修改类的成员变量并且返回值在外部代码中不能被修改


结尾

使用 const 修饰类成员函数可以提供额外的安全性和约束,通过 const 修饰的成员函数,编译器可以对其进行一些优化,在某些情况下还能够调用 const 成员函数来访问 const 对象。同时,也能够帮助开发人员识别和避免意外的修改操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1068898.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

免杀对抗-宏免杀

CS生成宏&上线 生成宏 1.cs生成宏,如下图操作 2.点击复制宏代码,保存下来 cs上线 注:如下操作使用的是word,同样的操作也适用于Excel 1.新建一个word文档,使用word打开。点击文件—— 2.更多——选项—— 3.自定义…

一文教你如何发挥好 TDengine Grafana 插件作用

作为当前最流行的图形化运维监控解决方案之一,Grafana 提供了一个灵活易用的界面,可以连接多种不同的数据源,包括时序数据库(Time Series Database)、云服务、监控系统等,然后从这些数据源中提取数据并实时…

从零开始的C++(七)

1.malloc、free和new、delete的区别: 1、.malloc、free是函数,new、delete是运算符。 2、malloc不会调用构造函数,new可以调用构造函数。 3、malloc开辟失败返回NULL,new失败会捕捉异常。 4、malloc不会自动计算类型大小&…

Intewell工业操作系统的来龙去脉

Intewell操作系统是由科东软件自主研发的工业嵌入式实时操作系统,是新一代工业控制系统承上启下的平台,致力于解决工业现场层操作系统的自主可控、安全可信问题,助力企业数字化转型,实现工业互联网的数字化、网络化、智能化发展&a…

Uniapp 新手专用 抖音登录 获取用户头像、名称、openid、unionid、anonymous_openid、session_key

TC-dylogin 一定请选择 源码授权版 教程 第一步 将代码拷贝至您所需要的页面 该代码位置:pages/index.vue 第二步 修改appid和secret 第三步 获取appid和secret 获取appid和secret链接 注意事项 为了安全,我将默认的自己的appid和secret在云函数中删…

Mind Map:大语言模型中的知识图谱提示激发思维图10.1+10.2+10.7

知识图谱提示激发思维图 摘要介绍相关工作方法第一步:证据图挖掘第二步:证据图聚合第三步:LLM Mind Map推理 实验实验设置医学问答长对话问题使用KG的部分知识生成深入分析 总结 摘要 LLM通常在吸收新知识的能力、generation of hallucinati…

深度解析四大主流软件架构模型:单体架构、分布式应用、微服务与Serverless的优缺点及场景应用

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

软件测试/测试开发丨送福利AI大模型应用开发实训营来啦~ 文末领大模型学习资料

点此获取更多相关资料 因为 AIGC 持续火热,越来越多的企业都需要借助大模型来为自己的业务赋能,也就是产出适合自己公司业务情况的智能化产品,这是目前程序员必须要面对的难题和挑战。如果要在企业内部落地相关引用,就需要员工具…

国泰君安期货:基于分布式架构的智能推送系统,满足单日亿级消息处理量

中国期货市场正经历着从量变到质变、加速提档的过程。近五年来,新增期权期货交易品种过百个,国际化品种大幅增加,市场交易规模迅速扩大。2022 年期货行业单边成交量约 70 亿手,为 2018 年的 2.5 倍,占全球总成交量的 8…

想要开发一款游戏, 需要注意什么?

开发一款游戏是一个复杂而令人兴奋的过程。游戏开发是指创建、设计、制作和发布电子游戏的过程。它涵盖了从最初的概念和创意阶段到最终的游戏发布和维护阶段的各个方面。 以下是一些需要注意的关键事项: 游戏概念和目标: 确定游戏开发的核心概念和目标…

Python WebSocket自动化测试:构建高效接口测试框架!

为了更高效地进行WebSocket接口的自动化测试,我们可以搭建一个专门的测试框架。本文将介绍如何使用Python构建一个高效的WebSocket接口测试框架,并重点关注以下四个方面的内容:运行测试文件封装、报告和日志的封装、数据驱动测试以及测试用例…

数据结构题型14-二叉树的遍历

文章目录 1、先序遍历2、中序遍历3、后序遍历5、非递归遍历5、层次遍历 参考博客: 二叉树遍历方法——前、中、后序遍历(图解) 1、先序遍历 2、中序遍历 3、后序遍历 5、非递归遍历 5、层次遍历

练[FBCTF2019]RCEService

[FBCTF2019]RCEService 文章目录 [FBCTF2019]RCEService掌握知识解题思路关键paylaod 掌握知识 ​ json字符串格式,命令失效(修改环境变量)–绝对路径使用linux命令,%0a绕过preg_match函数,代码审计 解题思路 打开题目链接,发现…

二维码智慧门牌管理系统:让城市管理更高效、更便捷

文章目录 前言一、二维码智慧门牌管理系统的特点二、二维码智慧门牌管理系统的应用三、二维码智慧门牌管理系统的开发解决方案 前言 随着城市化进程的加速,城市管理面临着越来越多的挑战。其中,门牌号码的管理问题一直困扰着城市管理部门。为了解决这个…

【排序算法】堆排序详解与实现

一、堆排序的思想 堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆(若不清楚什么是堆,可以看我前面的文章,有详细阐述)来进行选择数据&am…

投票礼物打赏流量主小程序开发

投票礼物打赏流量主小程序开发 投票功能:用户可以参与投票,选择自己支持的候选人或选项。礼物功能:用户可以给候选人或其他用户送礼物,以表示赞赏或支持。打赏功能:用户可以给候选人或其他用户打赏,以表示…

Transformer预测 | Pytorch实现基于Transformer的时间序列预测(含单步与多步实验)

文章目录 效果一览文章概述模型描述程序设计单步实验多步实验参考资料效果一览 文章概述 Transformer预测 | Pytorch实现基于Transformer的时间序列预测(含单步与多步实验) Transformer-singlestep.py 包含单步预测模型 Transformer-multistep.py 包含多步预测模型 这是单步预…

【kubernetes的三种网络】

kubernetes的三种网络 一、三种网络service网络(service是虚拟IP地址)pod网络(pod的IP地址 docker容器的IP)节点网络(网络服务器上的物理网卡IP) 二、其他网络flannel一、vxlan(隧道方案)1.定义2.优势3.工作…

软件定制开发的细节|网站搭建|APP小程序定制

软件定制开发的细节|网站搭建|APP小程序定制 在定制开发的过程中,一些小的细节往往能够影响到最终的产品质量和用户体验。下面我将为大家介绍一些软件定制开发的细节。 第一,明确需求。在定制开发之前,我们需要明确客户的需求和目标。只有明确…

C语言中常用的字符串处理函数(strlen、strcpy、strcat、strcmp)

文章目录 写在前面1. strlen1.1 函数介绍1.2 模拟实现 2. strcpy2.1 函数介绍2.2 模拟实现 3. strcat3.1 函数介绍3.2 模拟实现 4. strcmp4.1 函数介绍4.2 模拟实现 写在前面 本篇文章介绍了C语言中常用的字符串处理函数,包括strlen、strcpy、strcat和strcmp。文章…