【C++】基础篇二、引用详解

文章目录

  • 1.引用的概念和定义
  • 2.引用的特性
  • 3.引用的使用
      • 3.1 做函数返回值
      • 3.2 传参
    • 3.3 其他使用
  • 4.const的运用
    • 引用的权限问题;
    • const修饰引用;
  • 5.指针和引用的对比

在这里插入图片描述

1.引用的概念和定义

在介绍概念之前先说一下引用的符号——“ & ”;对于这个符号特别容易和取地址的符号——“ & ”混淆,要注意区分;

对于引用我们把它套入生活中可以更好的理解,比如我们给李明起个外号叫—“李四”,这里的 ”李四“ 在C++中就可以被叫做——引用,所以引用其实就相当于给变量起了一个别名,它的本质还是变量;

2.引用的特性


1.引⽤在定义时必须初始化

2.⼀个变量可以有多个引⽤

3.引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体

#include<iostream>
using namespace std;
int main()
{int a = 0;// 引⽤:b和c是a	的别名int& b = a;int& c = a;// 也可以给别名b取别名,d相当于还是a的别名int& d = b;++d;// 这⾥取地址我们看到是⼀样的cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << &d << endl;return 0;
}

在代码中,我们定义了一个变量“a”,对它取引用别名 “b” 之后,我们还可以在再对a取别名c,这两个都是a的引用,所以**引用(别名)的数量不受限制;**
然后我们也可以再对别名b取别名d,但是别名d还是a的别名;
而且当我们对别名d进行自增时,本质上相当于是对变量a的自增
引用时取的别名是不会在内存中有新的地址的,它与变量a(引用主体)的地址相同(共用一个地址)
在这里插入图片描述

#include<iostream>using namespace std;int main(){int a = 10;// 编译报错:“ra”: 必须初始化引⽤//int& ra;int& b = a;int c = 20;b = c;// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向, // 这⾥是⼀个赋值cout << &a << endl;cout << &b << endl;cout << &c << endl;return 0;
}

代码中当我们定义一个变量“ra”而没对他初始化时会报出下面的错误
在这里插入图片描述
所以**引用并不像指针一样,引用的主体必须初始化**;

对于引用时有多个主体的问题:

#include<iostream>
using namespace std;
int main()
{//int a = 10;//编译报错:“ra”: 必须初始化引⽤/*int& ra;int& b = ra;int c = 20;b = c;*/// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向, // 这⾥是⼀个赋值int a = 10;int c = 20;int& b = a;int& b = c;cout << &a << endl;cout << &b << endl;cout << &c << endl;return 0;
}

在这里插入图片描述
>引用主体只能有一个;

3.引用的使用

3.1 做函数返回值

1.•
引⽤在实践中主要是于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变被引⽤对象。
在c++中通过引用返回可以避免拷贝大型对象,提高性能。但需要注意避免返回局部变量的引用,因为这会导致悬挂引用(dangling reference,指向已被释放的内存地址。避免在删除对象后立即使用其引用)。

#include <iostream>
#include <string>
using namespace std;std::string& getString() 
{static std::string str = "Hello, World!";return str;
}int main() 
{std::string& refStr = getString();std::cout << refStr << std::endl; // 输出 Hello, World!return 0;
}

3.2 传参

2.•
引⽤传参跟指针传参功能是类似的,引⽤传参相对更⽅便⼀些。
在c++中传参分为值传参,引用传参
1 .传值:函数接收参数的副本,在函数内部对参数的修改不会影响外部变量
2.传引用:函数接收参数的引用,直接操作原始数据,避免了不必要的拷贝,提高了效率。

#include <iostream>void modifyValue(int& x) {x = 10;
}int main() {int a = 5;modifyValue(a);std::cout << "a: " << a << std::endl; // 输出 a: 10return 0;
}

3.3 其他使用

引用不仅能对变量进行引用,还可以对数组,指针引用:

1.在引用数组时,必须要知道数组的大小;

#include<iostream>
using namespace std;int main()
{int a = 10;int b = 10;int arr[5] = { 1,2,3,4,5 };int& x = ar[0];  //okint(&x)[5] = ar; //ok   没有[5]无法编译通过return 0;
}

2.引用指针时,跟引用变量一样,都是对引用主体取别名;

4.const的运用

引用的权限问题;

用const来修饰引用,主要的是涉及到一个权限的问题,在C++中权限只能缩小不能放大,而const在通常情况下可以帮我们解决这个问题;

//修改前
//void Count(int& s)
//{//}
//修改后
void Count(const int& s)
{}
int main{//int a = 0;// 权限平移int& ra = a;// 指针和引用赋值中,权限可以缩小,但是不能放大const int b = 1;// rb引用b,b只有可读权限,rb可读可写,权限放大,不允许//int& rb = b;// 权限平移const int& rb = b;// rra引用a,权限缩小了,允许const int& rra = a;Count(a);//可以Count(b);//不可以,传参时候b的权限扩大了Count(rra);//不可以,同上
}

使用const可以控制权限的大小;在我们修改函数Count之前,传 “b” 和 “rra” 都会因为权限放大而报错,这时我们就需要在函数参数中加入const来修饰参数体,加上const之后,a权限缩小,被允许,b和rra权限平移也可以

const修饰引用;

const T &p:表示p引用的对象的值不能通过p修改;

int main()
{	int n = 1;	const int& p = n;p++;}

在代码中,p是n的引用,由于引用被const限制不能改变,但是我们可以通过改变主体来改变p;

#include<iostream>
using namespace std;int mian()
{int n = 1;	const int& p = n;	n++;	cout << p;
}

5.指针和引用的对比

在C++中,引用和指针都是用于间接访问其他变量的工具,但它们之间存在显著的差异。以下是对引用和指针的详细对比:

一、定义与概念
引用:
引用是某个已存在变量的别名。
引用在定义时必须初始化,且一旦初始化后,就不能再改变为其他变量的引用。
指针:
指针是存储变量地址的变量。
指针可以在任何时候指向不同的变量,也可以为空(即指向NULL或nullptr)。
二、内存管理
引用:
引用不需要显式分配或释放内存。
当引用所引用的对象离开作用域时,引用自动失效,无需手动处理。
指针:
指针需要显式分配和释放内存,通常使用new和delete(或在C语言中使用malloc和free)。
若忘记释放内存,可能会导致内存泄漏。
三、操作与灵活性
引用:
引用操作相对简单,不需要解引用操作符()。
引用不支持空引用,必须始终引用一个有效的对象。
引用不支持算术运算,因为引用不是一个对象,而是一个别名。
指针:
指针操作相对复杂,需要使用解引用操作符(
)来访问指针所指向的对象。
指针可以为空,且支持算术运算(如指针加减)。
指针支持操作符重载,可以重载指针相关的操作符以实现自定义行为。
四、使用场景与优缺点
引用:
优点:使用简单、安全,不容易出错。
缺点:不够灵活,一旦初始化后不能改变引用的对象。
使用场景:常用于函数参数传递(特别是需要修改参数值时)、返回值以及作为复合类型的成员(如类的成员变量)。
指针:
优点:灵活性强,可以指向不同的对象,支持动态内存分配和数据结构(如链表、树等)。
缺点:容易出错(如悬挂指针、野指针等),需要手动管理内存。
使用场景:动态内存分配、数据结构实现、函数参数传递(特别是传递数组或对象的地址时)。
五、其他差异
sizeof运算:
引用:sizeof引用得到的是被引用类型的大小。
指针:sizeof指针得到的是指针类型的大小(与平台相关,32位平台下为4字节,64位平台下为8字节)。
多级引用与多级指针:
引用:不支持多级引用(即不能有一个引用的引用)。
指针:支持多级指针(即可以有一个指向指针的指针)。
综上所述,C++中的引用和指针各有优缺点和使用场景。在选择使用哪种方式时,应根据具体需求和编程情境来决定。引用通常更容易使用且更安全,而指针则提供了更多的灵活性和控制。

但是在汇编语言的层面上“引用”就是“指针”,这一观点我们可以从反汇编中得到;
在这里插入图片描述

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

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

相关文章

D3基础:绘制圆形、椭圆形、多边形、线、路径、矩形

在D3.js中&#xff0c;可以通过SVG元素来创建各种几何图形。以下是D3.js中常用的几何图形及其简单的创建方法&#xff1a; 1. 圆形 (Circle) 圆形是最基本的形状之一&#xff0c;可以通过<circle>标签来创建。 <!DOCTYPE html> <html> <head><met…

前端监控之sourcemap精准定位和还原错误源码

一、概述 在前端开发中&#xff0c;监控和错误追踪是确保应用稳定性和用户体验的重要环节。 随着前端应用的复杂性增加&#xff0c;JavaScript错误监控变得尤为重要。在生产环境中&#xff0c;为了优化加载速度和性能&#xff0c;前端代码通常会被压缩和混淆。这虽然提升了性…

MySQL的表的约束以及查询

本篇文章继续给大家梳理MySQL的操作 目录 表的约束 空属性 默认值 列描述 0填充 主键 主键常识 添加主键 删除主键 复合主键 自增长 唯一键 外键 单/多行输入与全/指定列的插入 全列输入 单行输入 多行插入 指定列插入 单行输入 多行插入 插入否则更新 替换…

MySQL 日志 主从复制

1. 日志 学习链接&#xff0c;click mysql中有4种日志&#xff1a; 错误日志二进制日志查询日志慢查询日志 1.1 错误日志 错误日志是MySQL中最重要的日志之一&#xff0c;它记录了当mysqld启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息。当…

自动驾驶系列—深入解析自动驾驶车联网技术及其应用场景

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

基于YOLOv8深度学习的公共卫生防护口罩佩戴检测系统(PyQt5界面+数据集+训练代码)

在全球公共卫生事件频发的背景下&#xff0c;防护口罩佩戴检测成为保障公众健康和控制病毒传播的重要手段之一。特别是在人员密集的公共场所&#xff0c;例如医院、学校、公共交通工具等地&#xff0c;口罩的正确佩戴对降低病毒传播风险、保护易感人群、遏制疫情扩散有着至关重…

vue使用List.reduce实现统计

需要对集合的某些元素的值进行计算时&#xff0c;可以在计算属性中使用forEach方法 1.语法&#xff1a;集合.reduce ( ( 定义阶段性累加后的结果 , 定义遍历的每一项 ) > 定义每一项求和逻辑执行后的返回结果 , 定义起始值 ) 2、简单使用场景&#xff1a;例如下面…

【Linux】进程的优先级

进程的优先级 一.概念二.修改优先级的方法三.进程切换的大致原理&#xff1a;四.上下文数据的保存位置&#xff1a; 一.概念 cpu资源分配的先后顺序&#xff0c;就是指进程的优先权&#xff08;priority&#xff09;。 优先权高的进程有优先执行权利。配置进程优先权对多任务环…

【软件工程】一篇入门UML建模图(类图)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…

AWTK-WIDGET-WEB-VIEW 实现笔记 (3) - MacOS

MacOS 上实现 AWTK-WIDGET-WEB-VIEW 有点麻烦&#xff0c;主要原因是没有一个简单的办法将一个 WebView 嵌入到一个窗口中。所以&#xff0c;我们只能通过创建一个独立的窗口来实现。 1. 创建窗口 我对 Object-C 不熟悉&#xff0c;也不熟悉 Cocoa 框架&#xff0c;在 ChatGPT…

QT仿QQ聊天项目,第三节,实现聊天界面

一&#xff0c;界面控件示意图 界面主要由按钮QPushButton,标签QLabel,列表QListWidget 要注意的是QListWidget既是实现好友列表的控件&#xff0c;也是实现聊天气泡的控件 二&#xff0c;控件样式 QPushButton#btn_name {border:none;}QPushButton#btn_close {border:1px;bac…

微信小程序自定义顶部导航栏(适配各种机型)

效果图 1.pages.js&#xff0c;需要自定义导航栏的页面设置"navigationStyle": "custom" 2.App.vue,获取设备高度及胶囊位置 onLaunch: function () {// 系统信息const systemInfo uni.getSystemInfoSync()// 胶囊按钮位置信息const menuButtonInfo uni.…

Android Studio开发学习(五)———LinearLayout(线性布局)

一、布局 认识了解一下Android中的布局&#xff0c;分别是: LinearLayout(线性布局)&#xff0c;RelativeLayout(相对布局)&#xff0c;TableLayout(表格布局)&#xff0c; FrameLayout(帧布局)&#xff0c;AbsoluteLayout(绝对布局)&#xff0c;GridLayout(网格布局) 等。 二、…

C++:哈希拓展-位图

目录 一.问题导入 二.什么是位图? 2.1如何确定目标数在哪个比特位? 2.2如何存放高低位 2.3位图模拟代码实现 2.3.1如何标记一个数 2.3.2如何重置标记 2.3.3如何检查一个数是否被标记 整体代码实现 标准库的Bitset 库中的bitset的缺陷 简单应用 一.问题导入 这道…

实用教程:如何无损修改MP4视频时长

如何在UltraEdit中搜索MP4文件中的“mvhd”关键字 引言 在视频编辑和分析领域&#xff0c;有时我们需要深入到视频文件的底层结构中去。UltraEdit&#xff08;UE&#xff09;和UEStudio作为强大的文本编辑器&#xff0c;允许我们以十六进制模式打开和搜索MP4文件。本文将指导…

Spring Boot 接口防重复提交解决方案

文章目录 前言使用Token机制实现步骤1.生成Token2.传递Token3.验证Token 使用Redis实现步骤1.引入Redis依赖2.生成Token3.传递Token4.验证Token 使用Spring AOP实现步骤1.定义注解2.创建切面3.使用注解 总结 前言 在Web开发中&#xff0c;防止用户重复提交表单是一个常见的需求…

Linux性能优化之火焰图简介

Linux 火焰图&#xff08;Flame Graph&#xff09;是一种可视化工具&#xff0c;用于分析程序性能问题&#xff0c;尤其是 CPU 使用情况。它展示了程序中函数调用的层次结构和各个调用栈占用的时间比例。 以下是详细介绍&#xff0c;包括火焰图的工作原理、生成步骤和实际使用中…

笔记|M芯片MAC (arm64) docker上使用 export / import / commit 构建amd64镜像

很简单的起因&#xff0c;我的东西最终需要跑在amd64上&#xff0c;但是因为mac的架构师arm64&#xff0c;所以直接构建好的代码是没办法跨平台运行的。直接在arm64上pull下来的docker镜像也都是arm64架构。 检查镜像架构&#xff1a; docker inspect 8135f475e221 | grep Arc…

【JavaWeb】JavaWeb入门之XML详解

目录 1.XML介绍 1.1.XML概述 1.1.1.什么是XML 1.1.2.XML的作用 1.1.3.XML与HTML的比较 1.1.4.XML和properties&#xff08;属性文件&#xff09;比较 1.1.5.W3C组织 1.2.XML语法概述 1.2.1.XML文档展示 1.2.2.XML文档的组成部分 1.3.XML文档声明 1.3.1.什么是XML文…

spring源码02-spring容器启动(容器初始化+bean实例化)源码解读【常见面试题】

文章目录 【README】【1】spring容器初始化及bean实例化步骤列表【2】spring容器初始化源码【2.1】容器初始化主要步骤总结&#xff1a;【2.2】容器初始化详细步骤源码分析 【3】bean实例化源码【3.1】bean实例化主要步骤总结&#xff08;非常重要&#xff09;【3.1.1】 bean生…