【深入理解C++】左值引用、常引用、右值引用、std::move()函数

2023/11/30 3:53:37

文章目录

  • 1.左值引用
  • 2.常引用
    • 2.1 const引用可以指向临时数据
    • 2.2 const引用可以指向不同类型的数据
    • 2.3 const引用作为函数参数
  • 3.右值引用
  • 4.std::move()函数

1.左值引用

左值引用只能绑定到左值上,不能绑定到右值上。

左值引用不能绑定到临时变量上,因为临时变量被系统当作右值。

所有变量都是左值,因为它们是有地址的。

任何函数里边的形参都是左值。

#include <iostream>
using namespace std;

int main()
{
	int& ref1 = 20; // 错误,左值引用不能绑定到右值上

	int a = 10, b = 20;

	int& ref2 = a; // 正确,左值引用能绑定到左值上	

	int& ref3 = a + b; // 错误,左值引用不能绑定到右值上

	return 0;
}

返回左值引用的函数、赋值运算符、下标运算符、解引用运算符、前置递增运算符、前置递减运算符等,返回的都是左值,可以将左值引用绑定到这类表达式的结果上。

#include <iostream>
using namespace std;

int main()
{
	int i = 10;
	int& ref = ++i; // 左值引用可以绑定到左值上,ref就变成了i的别名
	i += 5;
	cout << i << endl; // 16
	cout << ref << endl; // 16

	return 0;
}

2.常引用

引用可以被 const 修饰,这样就无法通过引用修改数据了,称为常引用。const 必须写在 & 符号的左边,才能算是常引用。

引用 int &p 相当于 int* const p,常引用 const int &p 相当于 const int* const p

#include <iostream>
using namespace std;

int main() {

	int height = 20;
	int age = 10;

	// p1不能修改指向,但是可以利用p1间接修改所指向的变量
	int* const p1 = &age;
	//p1 = &height; // 报错
	*p1 = 30;
	cout << age << endl; // 30

	// ref1不能修改指向,但是可以通过ref1间接修改所指向的变量
	int & const ref1 = age;
	ref1 = 40;
	cout << age << endl; // 40

	// p2可以修改指向,但是不可以利用p2间接修改所指向的变量
	int const* p2 = &age;
	p2 = &height;
	//*p2 = 30; // 报错

	// ref2不能修改指向,也不可以通过ref2间接修改所指向的变量
	int const &ref2 = age; // 常引用
	//ref2 = 40; // 报错

	return 0;
}

2.1 const引用可以指向临时数据

举例1:const引用指向常量

#include <iostream>
using namespace std;

int main() {

	const int &ref = 30;

	return 0;
}

举例2:const引用指向表达式

#include <iostream>
using namespace std;

int main() {

	int a = 1;
	int b = 2;
	const int &ref = a + b;

	return 0;
}

举例3:const引用指向函数返回值

#include <iostream>
using namespace std;

int func() {
	return 8;
}

int main() {

	const int &ref = func();

	return 0;
}

2.2 const引用可以指向不同类型的数据

#include <iostream>
using namespace std;

int main() {
	int age = 10;

	const double &ref = age;

	return 0;
}

当常引用指向了不同类型的数据时,会产生临时变量,即引用指向的并不是初始化时的那个变量。

举例1:查看常引用指向相同类型数据的汇编代码

#include <iostream>
using namespace std;

int main() {

	int age = 10;
	const int &ref = age;
	age = 30;

	cout << age << endl; // 30
	cout << ref << endl; // 30

	return 0;
}

在这里插入图片描述

举例2:查看常引用指向不同类型数据的汇编代码

#include <iostream>
using namespace std;

int main() {

	int age = 10;
	const long &ref = age;
	age = 30;

	cout << age << endl; // 30
	cout << ref << endl; // 10

	return 0;
}

在这里插入图片描述

2.3 const引用作为函数参数

const引用作为函数参数时,可以接受const和非const实参。

非const引用作为函数参数时,只能接受非const实参。

const引用跟非const引用可以构成函数重载。

const引用作为函数参数时的上述规则也适用于const指针。

#include <iostream>
using namespace std;

int sum(int &v1, int &v2) {
	cout << "sum(int &v1, int &v2)" << endl;
	return v1 + v2;
}

int sum(const int &v1, const int &v2) {
	cout << "sum(const int &v1, const int &v2)" << endl;
	return v1 + v2;
}

int main() {

	// 非const实参
	int a = 10;
	int b = 20;
	sum(a, b);
	
	// const实参
	const int c = 10;
	const int d = 20;
	sum(c, d);
	
	sum(10, 20);

	return 0;
}

输出结果如下:

在这里插入图片描述

3.右值引用

右值引用只能绑定到右值上,不能绑定到左值上。右值引用通常绑定到一些即将销毁的或一些临时的对象上。

#include <iostream>
using namespace std;

int main()
{
	int&& ref1 = 10; // 正确,右值引用能绑定到右值上

	int a = 100, b = 200;

	int&& ref2 = a; // 错误,右值引用不能绑定到左值上

	int&& ref3 = a * b; // 正确,右值引用能绑定到右值上

	return 0;
}

返回非引用类型的函数、算术运算符、关系运算符、位运算符、后置递增运算符、后置递减运算符等,返回的都是右值,不能将左值引用绑定到这类表达式上,可以将常引用或右值引用绑定到这类表达式上。

#include <iostream>
using namespace std;

int main()
{
	int i = 10;
	int&& ref = i++; // 右值引用绑定到临时变量上,此后ref和i没有关系
	i += 5;
	cout << i << endl; // 16
	cout << ref << endl; // 10

	return 0;
}

4.std::move()函数

std::move() 的能力只有一个:把一个左值强制转换成一个右值。实际上这个函数根本就没有做移动的操作。

#include <iostream>
using namespace std;

int main()
{
	int i = 10;
	int&& ref = std::move(i); // 把一个左值强制转换成一个右值
	i = 20;
	cout << i << endl; // 20
	cout << ref << endl; // 20

	return 0;
}
#include <iostream>
using namespace std;

int main()
{
	int&& ref1 = 100;
	int&& ref2 = std::move(ref1); // 把一个左值强制转换成一个右值
	ref1 = 200;
	cout << ref1 << endl; // 200
	cout << ref2 << endl; // 200

	return 0;
}
#include <iostream>
using namespace std;

int main()
{
	string src = "I love China!";
	string dst = std::move(src); // string里的移动构造函数把src的内容转移到dst中去了,而不是std::move()转移的
	cout << "&src = " << &src << ", src = " << src << endl;
	cout << "&dst = " << &dst << ", dst = " << dst << endl;

	return 0;
}

输出结果如下:

在这里插入图片描述

#include <iostream>
using namespace std;

int main()
{
	string src = "I love China!";
	string&& ref = std::move(src); // 把一个左值强制转换成一个右值
	cout << "&src = " << &src << ", src = " << src << endl;
	cout << "&dst = " << &ref << ", dst = " << ref << endl;

	return 0;
}

输出结果如下:

在这里插入图片描述


http://www.jnnr.cn/a/136571.html

相关文章

equals与==判断相等

一、 判断相等&#xff0c;判断的是物理地址相等。 二、equals 判断相等 equals 与hashCode 都是Object的方法。 所有的类都继承于Object&#xff0c;如果不重写equals。equals判断相等&#xff0c;底层也是使用来判断物理地址相等。 public boolean equals(Object obj) {re…

[附源码]java毕业设计农产品网络销售系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Java#13(String Builder介绍及其常用办法)

目录 一.String Builder 1.理解:可以将String Builder当作一个容器,创建之后的内容是可以变的 2.作用:可以提高字符串的操作效率 二. StringBuilder中的常用方法 1.public StringBuilder append (任意类型) 添加数据&#xff0c;并返回对象本身 2.public StringBuild…

蚂蚁集团最新业绩出炉:净利润同比下降63%,连续三个季度下滑

11月17日&#xff0c;阿里巴巴集团&#xff08;简称“阿里”&#xff0c;HK:09988、NYSE:BABA&#xff09;公布2023财年第二季度&#xff08;对应自然年2022年第三季度&#xff09;业绩。财报显示&#xff0c;阿里巴巴2022年第三季度的收入为人民币2071.76亿元&#xff08;约合…

【freeRTOS】操作系统之六-低功耗模式

六&#xff0c;低功耗模式 本章节为大家讲解 FreeRTOS 本身支持的低功耗模式 tickless 实现方法&#xff0c;tickless 低功耗机制是当前小型 RTOS 所采用的通用低功耗方法&#xff0c;比如 embOS&#xff0c;RTX 和 uCOS-III&#xff08;类似方法&#xff09;都有这种机制。ti…

知物由学 | 弹幕蜂拥而入,智能审核平台如何用技术破局?

导读&#xff1a;弹幕的出现增加了视频观看者的深度参与感&#xff0c;弹幕也逐渐成为国内各大视频网站最基本的评论交互形式&#xff0c;本文将通过网易易盾在弹幕实现原理及交互方式方面的实践&#xff0c;具体介绍弹幕相较于传统聊天室的区别与实践经验&#xff0c;希望能为…

智芯传感MEMS压力传感器促进无人机跨入极其广阔的应用市场

2022年11月8日至13日&#xff0c;第十四届中国国际航空航天博览会在广东珠海国际航展中心举办。伴随着人工智能技术的进步&#xff0c;全球无人化装备的发展如火如荼。各式各样的无人机在无人化装备中可谓是一枝独秀&#xff0c;广受外界的高度关注。 据美国《Aviation Week&am…

STM32 GD32 标准库移植SFUD

本次移植是在官方源码的基础上进行移植的 本次介绍的两个软件包SFUD/FAL都与FLASH有关&#xff0c;并且都可以独立使用或者结合在一起使用&#xff0c;两个软件包都对操作系统无依赖&#xff0c;可以使用裸机移植&#xff0c;也很方便移植到各种系统。 这两个软件包的作者都是…

16.一篇文章学会django模型的使用

1.django模型简单示例 1.1 创建django项目 创建完项目&#xff0c;还需要创建django子项目 django-admin startproject model_study cd .\model_study\ python manage.py startapp model_app1.2配置应用 将模型对应的应用程序&#xff08;刚刚创建的子应用&#xff09;添加…

艾美捷试剂级SM-102解决方案

LNP是一种多组分系统&#xff0c;通常由可电离脂质或阳离子类脂质化合物、辅助脂质、胆固醇、保护剂聚乙二醇-脂质共轭物组成。 脂质纳米颗粒&#xff08;LNP&#xff09;是mRNA药物常用的载体。目前&#xff0c;BioNTech/辉瑞和 Moderna的mRNA疫苗都采用LNP作为运输载体&#…

Linux安全--iptables详解

目录 1、iptables介绍 2、iptables四表五链详解 3、iptables基本语法 4、实际操作 4.1 增加规则 4.2 删除规则 4.3 修改规则 5、命令语法总结 6、基本匹配条件 7、iptables进阶用法 7.1 iprange扩展模块 7.2 string扩展模块 8、iptables进行端口转发 1、iptables介绍 …

前端使用nginx部署项目到服务器

目录 一、下载nginx 二、启动 三、验证 四、windows的操作指南 五、目录介绍 六、部署 一、下载nginx 下载地址&#xff1a;https://nginx.org/en/download.html 二、启动 两种方法&#xff1a; 1&#xff09; 直接双击该目录下的"nginx.exe"&#xff0c;即…

Push-Relabel算法相关阅读

Push-Relabel算法相关阅读1.Push-Relabel算法思想2.Push-Relabel算法原理示意图3.Push-Relabel算法具体实例4. 网络流各类算法简单总结与比较5. Push-Relabel 预流推进算法6. Push-Relabel算法(最大流)1.Push-Relabel算法思想 对于一个网络流图: 该算法直观可以这样理解&#…

【JVM学习】Jconsole 配置jmx 监控JVM

1. 配置jvm启动参数 在使用jconsole监控jvm之前&#xff0c;首先需要先打开jmx。启动jvm时&#xff0c;添加以下参数。jmx通过58088端口对外开放。 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port58088 -Dcom.sun.management.jmxremote.sslfalse -Dcom…

【快速上手系列】使用idea调百度AI接口实现内容审核(鉴黄)功能

【快速上手系列】使用idea调百度AI接口实现内容审核&#xff08;鉴黄&#xff09;功能 一、文本审核 步骤 1、百度AI开放平台 登录后点击控制台 点击应用列表——点击创建应用 填写一下信息然后创建 也可以配置审核策略 策略配置页面 然后回到概览——领取免费资源&#xf…

【猿创征文】Vue3 企业级优雅实战 - 组件库框架 - 7 组件库文档的开发和构建

本系列已更新文章&#xff1a; 分享一个实用的 vite vue3 组件库脚手架工具&#xff0c;提升开发效率 开箱即用 yyg-cli 脚手架&#xff1a;快速创建 vue3 组件库和vue3 全家桶项目 Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo Vue3 企业级优雅实战 - 组件库框架…

单商户商城系统功能拆解32—营销中心—消费奖励

单商户商城系统&#xff0c;也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法&#xff0c;例如拼团&#xff0c;秒杀&#xff0c;砍价&#xff0c;包邮…

觉哥java网站踩坑+bug记录(困扰一分钟以上的问题全记录)

1.jjuser 模块 运行启动类 报&#xff1a;找不到主类 jdk13... 这里我编译了 父工程 子模块没有被编译 静止的尘埃 小哥提示 &#xff1a;重新编译&#xff0c;然后试着编译子模块才正常 可能是idea bug 还是缓存啥的&#xff0c;正常编译父项目会把子模块一起编译 2.本地mysql…

菊风入选2022·爱分析保险科技厂商报告,为保险行业数智化转型赋能

随着数字化转型加速及大数据、人工智能等技术的日益精进&#xff0c;保险公司纷纷布局互联网赛道&#xff0c;采取“保险”与“科技”相结合的双引擎战略&#xff0c;赋予客户更快“速度”更暖“温度”的服务体验。可以说&#xff0c;保险科技作为保险和科技融合创新的成果与生…

【北亚数据恢复】硬盘出现坏道的数据恢复方案

经常使用电脑和移动硬盘的用户&#xff0c;如果察觉到电脑运行速度变得很慢&#xff0c;即使做了磁盘整理和系统重装操作后速度还是没有恢复到正常状态&#xff0c;这个时候就要小心是硬盘盘片出现坏道了。 如果这个时候用硬盘检测软件扫描硬盘就会发现扫描界面上出现很多绿块&…
最新文章