浅谈C/C++的常量const、指针和引用问题
今天我们来探讨C/C++中const、指针和引用的相关问题。这些概念是编程中的重要组成部分,它们的正确使用对于代码的可读性和可维护性至关重要。通过深入了解const的不可变性、指针的灵活性以及引用的简洁性,我们能够更好地掌握编程的精髓,并写出更加健壮和高效的代码😊😊😊
浅谈C/C++
- (1)const + 一级指针
- (2)const + 二级(多级)指针
- (3)引用操作符 &
先来看看对const的描述,C/C++中的const关键字用于声明一个常变量,即一个“不可修改的值”,通过使用关键字const,我们可以明确地指定一个变量、函数参数、函数返回值或类成员函数为只读,从而禁止对其进行修改,增强程序的健壮性。可见我们对于 const 的描述,常见为一个不可修改!!!,但在C和C++中,编译器对于 const 的反应也是 有差异的
1、我们先来看看.c文件 -》 C语言中的const,猜猜有何问题?
#include<stdio.h> int main() {const int a;int array[a] = { 0 };const int b = 0;b = 5;int* p = (int*)&a; *p = 30;printf("%d %d %d\n", a, *p, *(&a)); }我们不难想到
array[a]会报错,因为a没有被初始化,定义数组需要有一个常量值作为数组的长度,而a不可推测;b = 5,变量b为常变量,不可被修改- 然而,对于涉及到变量
p的语句,朋友是否有些疑惑🤔🤔🤔,p是指向变量a地址的普通指针,而*p = 30就是将它指向的地址上对应的值改为30,即分配给变量a的地址空间中的值 被改了🤣🤣🤣,我们去掉错误语句,加上a = 20后,看看执行的结果
由此可见,我们可以归纳出 C语言编译器 下有关
const的特性在C语言编译器中 a) const修饰可以不进行初始化,被看作常变量 b) 被const修饰的变量只是不能作为左值被修改,通过指针或引用的方式能够修改
2、我们再来看看.cpp文件 -》C++语言中的const,猜猜有何问题?
int main() {const int b;int c = 5;const int a = c;//const int a = 20;int array[a] = { 0 };int before = a;int* p = (int*)&a; *p = 30; int after = *(int*) & a;cout << before << endl << after << endl; cout << a << " " << *p << " " << *(&a) << endl;return 0; }不难想到
const int b;会报错,因为在C++中const修饰的变量被看作常量,不能够不对它进行初始化- 在
array[a]报错,变量a为变量c赋值而来,而c是一个变量,赋给变量a后,变量a也作为变量,而array[]里需要一个常量,所以出现错误,如下图
除去错误语句,把const int a = 20后的执行结果由此我们可以了解到
在C++语言编译器中 a) const修饰的变量必须初始化,不能作为左值 b) 被const修饰的变量只是不能作为左值被修改,通过指针或引用的方式能够修改 c) 被const修饰的变量被叫做常量,若直接赋值一个变量,不能直接作为数组的长度 c) 在C++编译器中,执行程序遇到const变量的时候,会直接被看作是常量,直接用初值替换,即*(&a) -> 20
本来我们使用const修饰变量的目的就是保证变量不被修改,然上面我们能够看到,如果我们把一个常量的地址泄露给了一个普通指针或者引用,那么就会有被修改的风险,因此我们需要对此问题做相应的处理,也就是下面我们将要介绍的 const + 指针的结合
📢📢📢注意:在C++语言规范中,const修饰的类型是离它最近的类型
(1)const + 一级指针
我们先来看看一级指针 + const的情况,如下:
//根据上面的注意项,有
const int *p; -> const修饰int,即值*p不可修改,指针可以任意指向p = &a
int const *p; -> const修饰int,同上
int* const p; -> const修饰int*,即指针指向p不可修改,值*p可以任意
int* const *p; -> const同时修饰int*和int,都不能修改

看到这,我们就能够自己解决:当泄露了常量的指针或引用时,常量可能被修改的问题。但是对于const和指针的各种组合类型中,也并非都能够相互进行强制转化的。
📢📢📢这里又需要注意一点:const右边如果没有指针*的话,const是不会参与进推测的类型
int* q1 = nullptr;
int* const q2 = nullptr;
const int* q3 = nullptr;
int const* q4 = nullptr;
int* const* q5 = nullptr;
cout << typeid(q1).name() << endl; // -> int*
cout << typeid(q2).name() << endl; // -> int*
cout << typeid(q3).name() << endl; // -> const int* / int const*
cout << typeid(q4).name() << endl; // -> const int* / int const*
cout << typeid(q5).name() << endl; // -> int* const*
//以上代码,朋友可以自己去验证一下是否正确
这里我们再给出一段代码,来看看是否正确🤔🤔🤔
#include<iostream> using namespace std;int main() {int a = 5;const int* pp = &a;//const int* pp = nullptr;int* qq = p;//cout << typeid(pp).name() << endl;char s = 'a';const char* ss = &s;char* sss = ss;return 0; }整形常量指针
p指向的是普通变量a的地址,整形变量指针p,也是普通变量a的地址,既然是普通变量,那么普通变量a的值应该是能被修改是吧🤫🤫,然当我们放在visual studio 2022上时,发现它报错了!!!,其实这更变量a无关,若我们将pp指向nullptr,仍然是一样的结果。因为在类型上,编译器是禁止将const int*类型的数据转换成int*类型的,使用char等其他类型也是如此
(2)const + 二级(多级)指针
我们再来看看const + 二级(多级)指针的情况,如下:
const int**q; -> **q 不能被赋值
int* const *q; -> *q 不能被赋值
int** const q; -> q不能被赋值
📢📢📢注意:对于const + 多级指针 的结合,涉及到类型转化时
错误:const int* -> int* ;int** -> const int** ;int* const* -> int** //const修饰一级指针《=》 const* -> *《=》 const int* -> int* 是错误的!const int** -> int** ;正确:int* -> const int* ;int** -> int* const* 《=》 * -> const*《=》 int* -> const int* 是正确的!
这里我们给出一段代码,来看看是否正确🤔🤔🤔
#include<iostream> using namespace std; int main() {int a = 10;int* p = &a;const int **q = &p; // const int** <- int**return 0; }
这里我们可以把换换const int* *q,即*q是整形常量的指针 《=》p,所以当我们把一个整形常量的地址赋值给*q时,const int b = 20; *q = &b,相当于直接就修改了p,使其指向了常量的地址,把变量b的指针间接地泄露给了普通指针*p,系统报错!!!
—>
解决方法:const int* const*q = &p;
- 我们让其不能够给
*q赋值,即禁用*q = &b
(3)引用操作符 &
引用是C++种的一种特殊数据类型,它提供了对现有别名的访问,通过引用可以使用相同的变量名来访问同一个内存地址的内容,一旦被初始化后,它将一致引用同一个对象,并且不能再引用其他对象,因此引用也被叫做更安全的指针!对比一下指针和引用的区别:
- 引用是必须初始化的,指针可以不被初始化
- 引用只有一级,而指针有多级
- 在汇编层面上,定义或修改引用变量和指针变量是一样的
从以下代码即图例可以看出:
#include<iostream> using namespace std; void swap(int& a, int& b) { int t = a; a = b; b = t; } //引用底层还是转化为指针>实现 void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; }int main() {int a = 10, b = 20;swap(&a, &b);swap(a, b);int *p = &a;int &q = a;int array[5] = {};int (&vv)[5] = array;return 0;
引用又可分为两种:左值引用 和 右值引用
- 左值引用: 对象的一个命名引用,它绑定到左值(如一个具名变量),即有名字、有内存,通过左值引用,可以修改被引用对象的值。
- 右值引用: 对临时对象或将要销毁的对象的引用,它绑定到右值(如一个临时对象,一个匿名对象,或一个将要销毁的对象),通过右值引用,可以实现资源的高效转移和移动语义
#include<iostream>
using namespace std;
{int a = 10;//int &&b = a; //错误右值引用变量无法绑定到左值int &&c = 20; //c++11提供了右值引用,汇编指令上产生临时量const int &d = a; //左值引用可以指向左值int &e = a;int &f = c; //右值引用本身是一个左值return 0;

📢📢📢注意:左值引用变量能够拥有右值和左值,但右值引用变量只能引用右值
上面就是关于const 、 指针 、 引用的问题,学而不思则罔,思而不学则殆,下面给出几道题目,来检验一下我们的学习成果
A) int a = 10const int *p = &aint *q = p xxx
B) int a = 10int* const p = &aint *q = p gggC) int a = 10int* const p = &aconst int *q = p gggD) int a = 10int *p = &aconst int **q = &p xxxE) int a = 10int *p = &aint* const* q = &p gggF) int a = 10int *p = &aint ** const q = &p gggG) int a = 10int* const p = &aint **q = &p int** <- int* const*xxxH) int a = 10const int*p = &aint* const* q = &p int* const* <- const int**《=》 int* <- const int*xxx引用是不参与推测类型的I) int a = 10int *p = &aint *&q = p 《=》 int **q = &pgggJ) int a = 10int* const p = &aint *&q = p 《=》 int **q = &pxxxK) int a = 10int *p = &aconst int* &q = p; 《=》 const int**q = &pggg
🌻🌻🌻以上就是浅谈C/C++的常量const、指针和引用的有关问题,如果聪明的你浏览到这篇文章并觉得文章内容对你有帮助,请不吝动动手指,给博主一个小小的赞和收藏 🌻🌻🌻
相关文章:
浅谈C/C++的常量const、指针和引用问题
今天我们来探讨C/C中const、指针和引用的相关问题。这些概念是编程中的重要组成部分,它们的正确使用对于代码的可读性和可维护性至关重要。通过深入了解const的不可变性、指针的灵活性以及引用的简洁性,我们能够更好地掌握编程的精髓,并写出更…...
React三大属性---state,props,ref
react的三大属性 react的三大属性分别是state props 和ref 是传递数据的重要内容 State state是组件对象最重要的属性 包含多个key-value的组合呢 存在于组件实例对象中 基本使用 此时demo是通过onClick的回调 所以this是undefined 本来应该是window 但是局部开启了严格模…...
进程学习--02
在C语言中,一般使用fork函数开辟进程,这个函数开辟进程后会返回一个进程号,在子进程中会返回0,在父进程中会返回子进程的进程号。 int main(){int ret fork();if(ret<0){fprintf(stderr, "pid error");exit(-1);}e…...
简易版 RPC 框架实现 1.0 -http实现
RPC 是“远程过程调用(Remote Procedure Call)”的缩写形式,比较通俗的解释是:像本地方法调用一样调用远程的服务。虽然 RPC 的定义非常简单,但是相对完整的、通用的 RPC 框架涉及很多方面的内容,例如注册发…...
欧科云链做客Google Cloud与WhalerDAO专题论坛,畅谈Web3数据机遇
3月10日,由Google Cloud、WhalerDAO和baidao data主办,以Web3AI 2024 DATA POWER为主题的分享会在北京中关村举行。欧科云链高级研究员Jason Jiang受邀参加活动,带来“从链上数据发掘Web3时代的无限机遇”的主题分享。 Web3.0核心要素始终是链…...
计算机网络 TCP协议的流量控制
流量控制的功能就是让发送方的发送速率不要太快,以便让接收方来的及接受,因此可以说流量控制是一个速度匹配服务,匹配发送方的发送速率和接收方的读取速率。 TCP利用滑动窗口机制来实现流量控制,滑动窗口的基本原理是,…...
【基于HTML5的网页设计及应用】——改变文字和背景颜色
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...
面向对象编程第三式: 多态 (Java篇)
本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…...
[数据集][目标检测]草莓成熟度检测数据集VOC+YOLO格式412张3类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):412 标注数量(xml文件个数):412 标注数量(txt文件个数):412 标注类别…...
浅谈HTTP 和 HTTPS (中间人问题)
前言 由于之前的文章已经介绍过了HTTP , 这篇文章介绍 HTTPS 相对于 HTTP 做出的改进 开门见山: HTTPS 是对 HTTP 的加强版 主要是对一些关键信息 进行了加密 一.两种加密方式 1.对称加密 公钥 明文 密文 密文 公钥 明文 2.非对称加密 举个例子就好比 小区邮箱 提供一…...
JAVA八股文面经问题整理第3弹
文章目录 目录 文章目录 提问问题 问题1 问题2 问题3 问题4 问题5 问题6 问题7 问题8 问题9 问题10 问题11 问题12 问题13 问题14 问题15 问题16 问题17 问题18 写在最后 提问问题 JVM类加载机制?nginx怎么做到负载均衡?HashMap的红⿊树和扩容机制&…...
python 爬取人民新闻
基础信息获取: 要闻url:https://www.gov.cn/yaowen/liebiao/home.htm 下一页的url:https://www.gov.cn/yaowen/liebiao/home_1.htm 基础代码: import re import openpyxl import requests from lxml import etree import osdef …...
蓝桥杯刷题(九)
1.三国游戏 代码 #输入数据 nint(input()) Xlilist(map(int,input().split())) Ylilist(map(int,input().split())) Zlilist(map(int,input().split())) #分别计算X-Y-Z/Y-Z-X/Z-X-Y并排序 newXli sorted([Xli[i] - Yli[i] - Zli[i] for i in range(n)],reverseTrue) newYli …...
【NTN 卫星通信】 车辆物联网设备通过NTN和TN切换的应用场景
1 场景描述 对于有两个3GPP无线接入网服务的大面积农田和农场,物联网设备可以通过NTN和TN接入网同时受益于5G系统的双转向数据连接能力。 在这个用例中,我们有一个广域的农业自动化应用系统来控制农业车辆,例如,一个装有数百个…...
html5cssjs代码 014 布局框架
html5&css&js代码 014 布局框架 一、代码二、解释三、Bootstrap框架简介 Bootstrap 是一个流行的开源前端开发框架,它由Twitter公司(后独立为Bootstrap团队)创建并维护。Bootstrap 提供了一套现成的、响应式的用户界面组件和设计布局…...
[EFI]Lenovo Ideapad 530S-14IKB电脑 Hackintosh 黑苹果efi引导文件
硬件型号驱动情况主板 Lenovo Ideapad 530S-14IKB 处理器Intel i5 8250U✅已驱动内存8 GB DDR4 2400 MHz✅已驱动硬盘250 GB SSD M.2 PCI-E✅已驱动显卡Intel UHD Graphics 620✅已驱动声卡暂无更多详细信息✅已驱动网卡Realtek RTL8111✅已驱动无线网卡蓝牙DW1560 (BCM94352Z)…...
FFmpeg-aac、h264封装flv及时间转换
文章目录 时间概念流程api核心代码 时间概念 dts: 解码时间戳, 表示压缩帧的解码时间 pts: 显示时间戳, 表示将压缩帧解码后得到的原始帧的显示时间 时间基: time_base , 通常以ms为单位 时间戳: timestamp , 多少个时间基 真实时间:time_base * timest…...
TCP并发模型 || select || poll || epoll
TCP并发模型: 1.TCP多线程模型: 缺点: 1.创建线程会带来资源开销,能够实现的并发量比较有限 2.IO模型: 1.阻塞IO: 没有数据到来时,可以让任务挂起,节省CPU资源开销,提高系统效率 2.非阻塞IO: 程序未接收到数据时一直执行,效率很低 3…...
【开源】SpringBoot框架开发房屋出售出租系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…...
STM32的简单介绍
STM32是一种基于ARM Cortex-M内核的32位微控制器,由意法半导体公司开发和生产。STM32具有丰富的外设和功能,适用于各种应用场合,如工业控制、消费电子、物联网、人机交互等。STM32的优势包括低功耗、高性能、高可靠性、易于开发等。STM32的系…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...






