浅谈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的系…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...






