C++ 引用

2023-11-17

        引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

引用和指针

        引用很容易与指针混淆,它们之间有三个主要的不同:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。

创建引用

        假设变量名称是变量附属在内存位置中的标签,则可以把引用当成变量附属在内存位置中的第二个标签。因此,可以通过原始变量名称或引用来访问变量的内容。例如:

int i = 17;
int & r = i;
double d = 30.0;
double & s = d;

        注意:语句中的&运算符不是地址运算符,而是将 i 的类型声明为int &,即指向int变量的引用。

        在声明中,& 读作引用。因此,第一个声明可以读作 "r 是一个初始化为 i 的整型引用",第二个声明可以读作 "s 是一个初始化为 d 的 double 型引用"。下面的实例使用了 int 和 double 引用:

#include <iostream>

using namespace std;

int main()
{ 
	/* 声明简单的变量 */ 
	int i = 5;
	double j = 10.0;

	/* 声明引用变量 */ 
	int & m = i;
	double & n = j;

	cout << "Value of i : " << i << endl;
	cout << "Value of i reference : " << m << endl;

	cout << "Value of j : " << j << endl;
	cout << "Value of j reference : " << n << endl;

	return 0;
}

        编译和执行上面的代码:

Value of i : 5
Value of i reference : 5
Value of j : 10
Value of j reference : 10

        引用通常用于函数参数列表和函数返回值。

把引用作为参数

        使用引用来实现引用调用函数:

#include <iostream>

using namespace std;

void swap(int& x, int& y);  // 函数声明

int main()
{
	/* 局部变量声明 */ 
	int a = 100;
	int b = 200;

	cout << "交换前,a 的值:" << a << endl;
	cout << "交换前,b 的值:" << b << endl;

	swap(a, b);  //调用函数来交换值

	cout << "交换后,a 的值:" << a << endl;
	cout << "交换后,b 的值:" << b << endl;

	return 0;
}

void swap(int & x, int & y)  // 函数定义
{
	int temp; 

	temp = x; // 保存地址 x 的值 
	x = y;    // 把 y 赋值给 x 
	y = temp; // 把 x 赋值给 y  

	return;
}

         编译和执行上面的代码:

交换前,a 的值:100
交换前,b 的值:200
交换后,a 的值:200
交换后,b 的值:100

把引用作为返回值

        使用引用替代指针,会使 C++ 程序更容易阅读和维护。函数可以返回一个引用,方式与返回一个指针类似。

        当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。例如,请看下面这个简单的程序:

#include <iostream>

using namespace std;

double vals[] = { 10.1, 12.6, 33.1, 24.1, 50.0 };

/* 返回第i个元素的引用,ref是一个引用变量,ref引用 vals[i] */ 
double& setValues(int i) 
{
    double& ref = vals[i];

    return ref;   
}

int main()
{
    cout << "改变前的值" << endl;
    for (int i = 0; i < 5; i++)
    {
        cout << "vals[" << i << "] = ";
        cout << vals[i] << endl;
    }

    setValues(1) = 20.23; // 改变第 2 个元素
    setValues(3) = 70.8;  // 改变第 4 个元素

    cout << "改变后的值" << endl;
    for (int i = 0; i < 5; i++)
    {
        cout << "vals[" << i << "] = ";
        cout << vals[i] << endl;
    }

    return 0;
}

         编译和执行上面的代码:

改变前的值
vals[0] = 10.1
vals[1] = 12.6
vals[2] = 33.1
vals[3] = 24.1
vals[4] = 50
改变后的值
vals[0] = 10.1
vals[1] = 20.23
vals[2] = 33.1
vals[3] = 70.8
vals[4] = 50

        注意:当返回一个引用时,要注意被引用的对象不能超出作用域。所以返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。

int& func()
{
	int q;         // 若return q; 在编译时发生错误,因为局部变量q超出了作用域	
	static int x;  // 安全,x 在函数作用域外依然是有效的

	return x; 
}

        引用作为返回值,必须遵守以下规则:

  • 不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
  • 不能返回函数内部新分配的内存的引用。虽然不存在局部变量的被动销毁问题,可对于这种情况,会面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(函数内部新分配的内存)就无法释放,造成内存泄漏。
  •  可以返回类成员的引用,但最好是const。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 引用 的相关文章

  • 如何验证文件名称在 Windows 中是否有效?

    是否有一个 Windows API 函数可以将字符串值传递给该函数 该函数将返回一个指示文件名是否有效的值 我需要验证文件名是否有效 并且我正在寻找一种简单的方法来完成此操作 而无需重新发明轮子 我正在直接使用 C 但针对的是 Win32
  • 访问私人成员[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 通过将类的私有成员转换为 void 指针 然后转换为结构来访问类的私有成员是否合适 我认为我无权修改包含我需要访问的数据成员的类 如果不道德 我
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • Newtonsoft JSON PreserveReferences处理自定义等于用法

    我目前在使用 Newtonsoft Json 时遇到一些问题 我想要的很简单 将要序列化的对象与所有属性和子属性进行比较以确保相等 我现在尝试创建自己的 EqualityComparer 但它仅与父对象的属性进行比较 另外 我尝试编写自己的
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C#:如何防止主窗体过早显示

    在我的 main 方法中 我像往常一样启动主窗体 Application EnableVisualStyles Application SetCompatibleTextRenderingDefault false Application
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • Cython 和类的构造函数

    我对 Cython 使用默认构造函数有疑问 我的 C 类 Node 如下 Node h class Node public Node std cerr lt lt calling no arg constructor lt lt std e
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • clang 实例化后静态成员初始化

    这样的代码可以用 GCC 编译 但 clang 3 5 失败 include
  • 将 unsigned char * (uint8_t *) 转换为 const char *

    我有一个带有 uint8 t 参数的函数 uint8 t ihex decode uint8 t in size t len uint8 t out uint8 t i hn ln for i 0 i lt len i 2 hn in i
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • C 中的异或运算符

    在进行按位操作时 我在确定何时使用 XOR 运算符时遇到一些困难 按位与和或非常简单 当您想要屏蔽位时 请使用按位 AND 常见用例是 IP 寻址和子网掩码 当您想要打开位时 请使用包含或 然而 XOR 总是让我明白 我觉得如果在面试中被问
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • Linux系统查看CPU个数&超线程&线程数

    Linux系统查看CPU个数 超线程 线程数 cpu 核心数与线程数 Linux系统查看CPU个数 超线程 线程数 小命令 Linux查看CPU详细信息 简书 jianshu com Intel CPU产品规范 英特尔 产品 处理器 英特尔
  • win10用html文件做壁纸,利用win10自带工具制作动态壁纸的简单方法

    微软在最强大操作系统利用win10自带工具制作动态壁纸的简单方法的详细介绍 利用win10自带工具制作动态壁纸的简单方法 把图片做成动态壁纸 总共分4步 1 准备素材 2 素材导入 3 调整效果 4 导出视频 接下来 笔者就为分步讲解以下制
  • VMware安装CentOS7

    目录 一 安装CentOS 二 网络配置 三 虚拟机克隆 一 安装CentOS 1 进入VMware主页面 选择 创建新的虚拟机 2 进入新建虚拟机向导 配置类型选择 典型 3 浏览 选择下载好的iso文件 CentOS7驱动下载地址 Ce
  • vue-cli3.0+antd+select

    前言 通过和 iview 和 element antd 还是有他特殊的优势的 那就是功能更加丰富 当然 功能丰富同样代表着复杂程度相比较来说 更高了 这里来对他进行二次封装 此外 在我们实际应用的情况下会遇到给他赋值赋不上 用default
  • java中的类

    4 1 类是什么 1 类 类型 数据类型 复合数据类型 自定义复合数据类型 为什么有复合数据类型 基本数据类型就8种 在开发中远远不够 所以我们就需要一个可以根据自己的需求随时能制作出一个自己需要的数据类型 2 类 具有共同性质的一组事物的
  • sawyer机械臂环境搭建

    sawyer机械臂环境搭建 1 ros安装 2 sawyer sdk安装 3 sawyer sdk环境配置 4 测试 1 ros安装 ros的安装方法参考创客智造 注意安装ubuntu系统对应版本的ros 新版ros melodic可以在w
  • 数据结构--二叉树的顺序结构及实现

    文章目录 前言 堆 堆的概念以及结构 堆的搭建 堆的实现 前言 普通的二叉树是不适合用数组来存储的 因为这样会存在大量的空间浪费 但是完全二叉树却更适合用顺序结构存储 堆 堆的概念以及结构 堆的概念 堆是一种二叉树 可以用顺序结构的数组来存
  • TCP协议为什么是三次握手而不是两次

    1 主要是为了防止已经失效的连接请求报文突然有传送到了服务器 从而导致不必要的错误和资源的浪费 2 两次握手只能保证单项连接时通常的 因为TCP是一个双向传输协议 只有经过第三次握手 才能确保双向都可以接收到对方发送的数据
  • 【经典】markdown编辑器手册

    这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题 有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一个表格 设定内容居中 居左 居右 Sma
  • ubuntu 查看端口占用命令

    查看端口占用情况 netstat nultp
  • Android开发中访问服务器常用到的response.getStatusCode()的值各代表什么

    response getStatusCode 200 代表请求成功 response getStatusCode 303 代表重定向 response getStatusCode 400 代表请求错误 response getStatusC
  • 访问方法access method---单表访问方法(三十六)

    上篇文章回忆了innodDB的独立表空间和系统表空间的结构 因为需要梳理的知识点太多 所以额外用一篇 独立表空间 系统表空间总结 innoDB表空间 三十五 单表的访问方法 对我们开发来说 mysql就是个软件 用sql查询我们需要的数据
  • 基于布谷鸟算法结合灰狼算法求解最优目标

    基于布谷鸟算法结合灰狼算法求解最优目标 在本文中 我们将介绍如何使用布谷鸟算法和灰狼算法的组合来求解最优目标问题 我们将提供相应的MATLAB代码 以便读者可以直接实现和测试这种算法组合的效果 布谷鸟算法 Cuckoo Search Alg
  • 使用Git Bash从Git上下载代码到本地以及上传代码到码云Git

    前提是已经安装了GitBash 这个稍后再出教程 1 新建一个目录 存放下载下来的项目 我在D盘新建了一个 gitspace 文件夹 用来存放下载下来的项目 2 进入刚刚新建的文件夹 即进入 gitspace 点击鼠标右键 选择 Git B
  • 2021年国家平均工资出炉,你又被平均了吗?

    近期 国家统计局发布2021全国平均薪资 IT业年平均工资突破20万位于榜首 分行业门类看 IT行业年平均工资私营 非私营均位列第一 年平均工资最高的3个行业分别是信息传输 软件和信息技术服务业201506元 科学研究和技术服务业15177
  • Django基础入门⑧:Django路由详细讲解

    Django基础入门 Django路由 Django路由 路由分发函数 反向解析 反向解析应用 使用url标签实现反向解析 reverse 函数实现反向解析 reverse 函数简析 命名空间namespace 个人简介 以山河作礼 Pyt
  • mysql常用日期时间/数值函数

    author skate time 2013 05 16 1 日期时间函数 时间转化秒函数 time to sec mysql gt select time to sec 01 01 01 time to sec 01 01 01 3661
  • 将数组以逗号拼接_javascript将数组拼接成一个字符串

    这里记录下在JavaScript中如何将数组拼接成一个字符串 所谓的将数组拼接成一个字符串 意思就是将数组中的元素逐个拼接到一个字符串中 并加以特定的分隔符 在JavaScript中可以有两种方式 一种是Array对象提供的join 方法
  • Mysql-表关系多对多设计

    多对多 如 订单 和 商品 一个商品对应多个订单 一个订单包含多个商品 实现方式 建立第三张中间表 中间表至少包含两个外键 分别关联两方主键 DROP TABLE tb order DROP TABLE tb goods DROP TABL
  • C++ 引用

    引用变量是一个别名 也就是说 它是某个已存在变量的另一个名字 一旦把引用初始化为某个变量 就可以使用该引用名称或变量名称来指向变量 引用和指针 引用很容易与指针混淆 它们之间有三个主要的不同 不存在空引用 引用必须连接到一块合法的内存 一旦