C++引用(特性+使用场景+常引用)

news2024/10/7 14:30:53

文章目录

  • 1. 概念
  • 2. 关于别名的理解
  • 3. 引用的特性
    • 1.引用必须在定义时初始化
    • 2.一个变量可以有多个别名
    • 3.引用一旦引用一个实体,再不能引用其他实体
  • 4.使用场景
    • 1. 引用做参数
    • 2. 引用做返回值
      • 1. 传值返回
        • 是否为n直接返回
        • 临时变量作为返回值
      • 2. 传引用返回
        • 编译器傻瓜式判断
        • 减少拷贝
        • 调用者修改返回对象
      • 3. 例题
  • 5. 常引用
    • 权限放大
    • 权限保持
    • 权限缩小
    • 临时变量具有常性
    • 类型转换产生临时变量

1. 概念

  • 引用不是新定义一个变量,而是给已存在的变量取别名,编译器不会为引用变量开辟内存空间,它和它引用的变量公用同一块内存空间

  • 比如说 李逵,在家称为"铁牛", 江湖上人称"黑旋风" 这两个称号都是他的
    在这里插入图片描述

2. 关于别名的理解

#include<iostream>
using namespace std;
int main()
{
	int a = 10;//引用
	int& b = a;
	b = 20;
	return 0;
}
  • b是a的引用,也就是起了一个别名,a再取了一个名称
    在这里插入图片描述
  • 同时改变别名b的值,也会改变a本身的值

3. 引用的特性

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

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int& b;//错误举例
	return 0;
}
  • 若使用引用不初始化,b是谁的别名?

2.一个变量可以有多个别名

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int& b = a;
	int& c = a;
	int& d = a;
	return 0;
}
  • b、c、d都是a的别名

3.引用一旦引用一个实体,再不能引用其他实体

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int& b = a;
	int c = 2;
	b = c;
	return 0;
}

在这里插入图片描述

  • 由于b与c的地址不同,说明b不是c的别名 b值与c值相等,而是将c的值传给b

4.使用场景

1. 引用做参数

#include<iostream>
using namespace std;
void swap(int& pa, int& pb)
{
	int tmp = pa;
	pa = pb;
	pb = tmp;
}
int main()
{
	int a = 1;
	int b = 2;
	swap(a, b);
	cout << "a= " << a <<"  "<<"b=" << b << endl;
	return 0;
}

把pa作为a的别名,即a本身
把pb作为b的别名,即b本身
pa与pb的交换就可以看作a与b的交换

2. 引用做返回值

1. 传值返回

是否为n直接返回

#include<iostream>
using namespace std;
int count()
{
    int n = 0;
    n++;
    return n;
}
int main()
{
    int ret=count();
    return 0;
}

在这里插入图片描述
正常来说,是把n直接给ret,但是局部变量n随着count函数的销毁而销毁
所以ret再次访问到到原来函数栈帧,就会造成非法访问

所以说明并不是使用n作为返回值

临时变量作为返回值

在这里插入图片描述
将临时变量作为返回值
编译器是将n的值给予一个临时变量,临时变量的类型是int,再通过临时变量传给ret
临时变量通常是由寄存器(存4个字节/8个字节)充当

2. 传引用返回

编译器傻瓜式判断

#include<iostream>
using namespace std;
int count()
{
    static int n = 0;
    n++;
    return n;
}
int main()
{
    int ret=count();
    return 0;
}

static修饰后n在静态区,所以count栈帧的销毁不影响n,虽然n的值存在,但是依旧要通过临时变量来传递返回值,因为编译器是傻瓜式的处理问题.
此时临时变量是没必要存在,所以我们可以采用引用返回

减少拷贝

在这里插入图片描述
编译器将n的值传给临时变量,类型是int&,相当于n的别名,
再把临时变量传给ret,相当于将n本身传给ret,减少拷贝

调用者修改返回对象

#include<iostream>
using namespace std;

#define N 100
typedef struct arry//静态数组
{
    int a[N];
    int size;
}ay;
int& posat(ay& arr,int i)//传引用返回,返回的是arr.a[i]本身
{
    return arr.a[i];
}
int main()
{
 ay arr;
    int i = 0;
    for ( i = 0; i < N; i++)
    {
        posat(arr, i) = i;//将arr.a[i]的值进行赋值
    }
    for (i = 0; i < N; i++)//打印静态数组的值
    {
        cout << posat(arr, i) << " ";
    }
    return 0;
}


出了posat作用域还在,因为ay.a[i]属于结构体的局部变量,所以可以使用传引用返回,从而修改静态数组的值

3. 例题

#include<iostream>
using namespace std;
int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);
    Add(3, 4);
    cout << "Add(1,2) is :" << ret << endl;//7
        cout << "Add(1,2) is :" << ret << endl;//随机值
    return 0;
}
  • 这个程序本身是错误的,结果是未定义的在这里插入图片描述
  • 先调用Add(1,2),由于是传引用返回,将c值3传给临时变量(作为c值的别名),再将临时变量传给ret,即ret是临时变量的别名,同理,ret也为c值的别名 (若Add栈帧销毁后空间没有被清理,ret值为3,若空间被清理,则为随机值)

在这里插入图片描述

  • 调用同一个函数,建立栈帧大小相同,c处于位置也是相同,(若Add栈帧销毁后空间没有被清理,ret值为7,若空间被清理,则为随机值)
  • 第一次空间未被清理,ret值为7,cout是一次函数调用,会建立函数栈帧覆盖掉Add栈帧,所以下一次为随机值

5. 常引用

权限放大

#include<iostream>
using namespace std;
int main()
{
    const int c = 2;
    int& d = c;//错误 权限放大
    return 0;
}
  • c由const修饰,权限为只读, d权限为可读可写,将只读转化为可读可写是权限放大的表现,会报错
  • 说明权限不可以放大

权限保持

#include<iostream>
using namespace std;
int main()
{
    const int c = 2;
    const int& d = c;//权限保持
    return 0;
}

c的权限为只读,d的权限为只读
c和d的权限相同,可以使d作为c的别名

说明权限可以保持

权限缩小

#include<iostream>
using namespace std;
int main()
{
     int a = 5;
     const int& b = a;//权限缩小
     return 0;
}

a的权限为可读可写,b的权限为只读,b可以作为a的别名
说明权限可以缩小

临时变量具有常性

int count()
{
    int n = 0;
    n++;
    return n;
}
int main()
{
    const int& ret = count();
    return 0;
}
  • 传值返回,返回的是临时变量,ret作为临时变量的别名,临时变量具有常性,所以需加const修饰ret

类型转换产生临时变量

#include<iostream>
using namespace std;
int main()
{
    int i = 2;
    const double& d = i;
}
  • i的值传给临时变量,临时变量类型为double,再使d作为临时变量的别名,临时变量具有常性,所以d要有const修饰

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

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

相关文章

11、循环语句

目录 一、while语句 二、do…while语句 三、for语句 一、while语句 使用while语句可以执行循环结构&#xff0c;其一般形式如下&#xff1a; while语句的执行流程图&#xff1a; while语句首先检验一个条件&#xff0c;也就是括号中的表达式。当条件为真时&#xff0c;就执…

跟同事杠上了,用雪花算法生成的id做主键对MySQL性能有影响?

公司最近开发了一个新项目&#xff0c;设计表时由于有些字段需要对外展示&#xff0c;所以使用了雪花算法生成的id做主键。 不过有位同事对此提出了异议&#xff0c;认为雪花算法生成的id不是顺序递增的&#xff0c;会对MySQL的性能造成影响。 经过交流&#xff0c;发现持有这…

【Linux 系统运维基础】Linux目录 以及重要配置文件

Linux目录 以及重要配置文件 文本讲述了Linux中目录含义 以及我们工作中常用到的路径 1. 目录含义 2. 常用路径地址 2.1 网卡配置文件 /etc/sysconfig/network-scripts但是网卡的名称是有区别的&#xff0c;使用不同服务器生产商的名称是不同的。如下图&#xff1a; 网卡配置…

Window10下FFMPEG的安装与使用

文章目录一.FFMPEG介绍FFMPEG组成二.Windows10下FFMPEG安装三.FFMPEG的使用1.关键指令一.FFMPEG介绍 FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它…

字节前端面试题目2

1.为什么通常在发送数据埋点请求的时候使用的是 1x1 像素的透明 gif 图片&#xff1f; 1. 没有跨域问题&#xff0c;一般这种上报数据&#xff0c;代码要写通用的&#xff1b;&#xff08;排除 ajax&#xff09; 2. 不会阻塞页面加载&#xff0c;影响用户的体验&#xff0c;只…

基于SSM的图书购物商城设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

【C++】三大特性之继承

目录 一、继承的概念及定义 1.继承的概念 2. 继承定义 2.1定义格式 2.2继承关系和访问限定符 2.3继承基类成员访问方式的变化 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、友元与继承 六、继承与静态成员 七、复杂的菱形继承及菱…

机器学习中的数学原理——线性不可分

这个专栏主要是用来分享一下我在 机器学习中的 学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎 私信或者评论区留言&#xff01;这一篇就更新一下《 白话机器学习中的数学——线性不可分》&#xff01; 目录 一、什么是线性不可分 二…

用125行C语言编写一个简单的16位虚拟机

改博文用图文代码的方式详细描述了实现的具体过程&#xff0c;包含每一条指令的含义。 虚拟机 在计算领域&#xff0c;VM&#xff08;虚拟机&#xff09;是一个术语&#xff0c;指的是模拟/虚拟化计算机系统/架构的系统。 从广义上讲&#xff0c;有两类虚拟机&#xff1a; 系统…

每日一练11——最近公共祖先求最大连续bit数

文章目录最近公共祖先思路&#xff1a;代码&#xff1a;求最大连续bit数思路&#xff1a;代码&#xff1a;最近公共祖先 题目链接 思路&#xff1a; 题目所描述的满二叉树如下&#xff1a; 上述树中子节点与父节点之间的关系为root child / 2 所以如果a &#xff01; b&a…

递归算法整理

一、概述&#xff1a;递归算法是一种直接或者间接调用自身函数或者方法的算法。说简单了就是程序自身的调用。类似于数列&#xff0c;通过前几项的值推出后几项 二、递归算法的使用条件1.大问题可以拆分为若干小问题2.原问题与子问题除数据规模不同&#xff0c;求解思路完全相同…

自助Active Directory组订阅

在任何基于Windows的企业的身份与访问管理(IAM)战略中&#xff0c;Active Directory组扮演了至关重要的角色&#xff0c;因为它们用来控制对几个资源&#xff08;包括电子邮件通讯组&#xff09;的用户访问。反复地添加用户到组中和从组中移除用户构成了IT管理员工作的有机组成…

C#windows竞赛管理系统

中文摘要 为了提高竞赛项目信息的管理效率&#xff0c;本课题使用C#语言和SQL Server数据库系统开发了一个WinForm类型的竞赛管理系统对竞赛项目信息进行高效管理&#xff0c;以提升管理质量。本系统包含教师登录注册、教师信息修改模块、添加学生信息模块、删除学生信息模块、…

可编程直流电源的介绍 什么是可编程直流电源

现在各种的电子设备不断地发展&#xff0c;它们对直流供电的电源也有了更高的要求&#xff0c;相对于电子设备来说&#xff0c;用单一的直流电源是没有办法达到供电的要求&#xff0c;所以需要不同的直流电源来给电子设备供电。可编程直流电源就是这一种。在生产测试中&#xf…

java:获取本机IP,Linux环境下使用InetAddress.getLocalHost()方法获得127.0.0.1

知道InetAddress.getLocalHost()方法是可以获取本地ip的&#xff0c;但是在mac电脑上执行的时候&#xff0c;偶尔会得到127.0.0.1的输出&#xff0c;这样拿到本地ip很不稳定&#xff0c;感觉就很不靠谱了 目录InetAddress.getLocalHost()方法获取本地IP不靠谱原因获取本地IP的靠…

Python中最简单不过的print语句讲解

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python、c 主页&#xff1a;阿玥的小东东 前面使用 print() 函数时&#xff0c;都只输出了一个变量&#xff0c;但实际上 print() 函数完全可以同时输出多个变量&#xff0c;而且它具有更多丰富的功能。 目录 1.格式 2.参考 1…

leetcode-每日一题-1334-阈值距离内邻居最少的城市(中等,floyd)

佛洛依德的变化问法&#xff0c;我之前有文章介绍过佛洛依德算法&#xff0c;不难可以去看看。1334. 阈值距离内邻居最少的城市难度中等94收藏分享切换为英文接收动态反馈有 n 个城市&#xff0c;按从 0 到 n-1 编号。给你一个边数组 edges&#xff0c;其中 edges[i] [fromi, …

如何做数据清洗?

一.预处理阶段 预处理阶段主要做两件事情&#xff1a; 一是将数据导入处理工具。通常来说&#xff0c;建议使用数据库&#xff0c;单机跑数搭建MySQL环境即可。如果数据量大&#xff08;千万级以上&#xff09;&#xff0c;可以使用文本文件存储python操作的方式 而是看数据…

04-jQuery

目录1、jQuery 的属性操作2、jQuery 练习2.1、全选&#xff0c;全不选&#xff0c;反选3、DOM 的增删改4、jQuery 练习二4.1、从左到右&#xff0c;从右到左练习4.2.动态添加、删除表格记录5、CSS 样式操作。6、jQuery 动画练习 6.1、CSS_动画 品牌展示7、jQuery 事件操作7.1、…

vue3+vite+ElementPlus安装和使用

按照vue3官网安装 > npm init vuelatest这一指令将会安装并执行 create-vue&#xff0c;它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示&#xff1a; ✔ Project name: … <your-project-name> ✔ Add TypeScript? ……