左值右值, 左值引用右值引用,完美转发

news2024/10/6 10:30:39

一. 左值和右值

左值: 可以取地址的对象
右值: 不可以取地址的对象

double x=1.0, y = 2.0;
1;				// 字面量, 不可取地址, 是右值
x + y;			// 表达式返回值, 不可取地址, 是右值
max(x, y);		// 传值返回函数的返回值 (非引用返回)

总结就是: 根据是否可以取地址来区分是左值还是右值

二.左值引用和右值引用

左值引用: 对左值的引用, 给左值起别名, 主要是为了避免对象拷贝.

int a = 1;
int& la = a;

右值引用: 对右值的引用, 给右值起别名, 主要是为了延长对象的生命周期

int&& ra = 10;

注意, 右值引用变量, 其实是左值, 可以对它取地址和赋值

int x = 1, y = 2;
int&& right_ref = x + y;
cout << right_ref << endl;
right_ref = 10;
cout << right_ref << endl;

2.1 左值引用指向右值 和 右值引用指向左值

左值引用可以指向右值, 需要const来修饰, 这一点在方法里很常用, 比如push_back接口, 并且const修是, 所以即使传进来的是右值, 也没关系.

void test(const int& a)
{
	cout << a << endl;
}


int main() {
	int a = 1;
	int&& ra = move(a);
	test(a);
	test(ra);
}

右值引用可以指向左值, 需要std::move(v)

int a = 1;
int&& ra = move(a);
cout << ra << endl;
a = 2;
cout << ra << endl;
ra = 3;
cout << a << endl;

三. 左值引用的意义

传参返回值时, 避免对象拷贝, 节省了内存, 提搞了效率

class A
{
public:
	int _a;
	A(int a) : _a(a) {};
	// 返回值时, 避免拷贝
	A& operator +=(const int& i)
	{
		_a += i;
		return *this;
	}
};

// 传参时, 避免拷贝
void test(const A& a)
{
	cout << a._a << endl;
}


int main() {
	A a(1);
	test(a);
	a += 1;
	test(a);
}

但是在返回值返回左值引用时, 如果返回的是局部变量, 那么除了函数作用域是不行的

class A
{
public:
	int _a;
	A(int a) : _a(a) {};
	A& operator +=(const int& i)
	{
		A a(_a);
		// 返回局部变量, 会直接报错
		return *a;
	}
};

int main() {
	A a(1);
	a += 1;
}

四. 右值引用的意义

将一个对象中的资源移动到另一个对象(资源控制权的转移)。
拷贝构造: const左值引用
移动构造: 右值引用
移动赋值: const左值引用, 是运算符重载
用例如下

class A
{
public:
	int _a;
	A(int a) : _a(a) 
	{
		cout << "构造函数" << endl;
	};
	A(const A& a)
	{
		cout << "拷贝构造函数" << endl;
		_a = a._a;
	}
	A(A&& a) noexcept
	{
		cout << "移动构造函数" << endl;
		_a = a._a;
	}
	A& operator=(const A& a) noexcept
	{
		cout << "移动赋值函数" << endl;
		_a = a._a;
		return *this;
	}
};

A test()
{
	A a(1);
	cout << &a << endl;
	// 但是现代编译器中, 这里已经不执行移动构造函数了, 用了更好的优化方式
	return a;
}

int main() {
	A a = test();
	cout << &a << endl;

	A a2 = a;
	A a3 = std::move(a);
	A a4(1);
	a4 = std::move(a3);
}

执行结果
在这里插入图片描述

五. 完美转发

5.1 前提知识

函数模板中的&&不表示右值引用, 而表示万能引用
不完美转发的例子

void f(int& x)
{
	cout << "左值引用" << endl;
}

void f(const int& x)
{
	cout << "const 左值引用" << endl;
}

void f(int&& x)
{
	cout << "右值引用" << endl;
}

void f(const int&& x)
{
	cout << "const右值引用" << endl;
}

template<typename T>
void test(T&& t)
{
	f(t);
}

int main() {
	int a = 1;
	test(a);
	const int b = 1;
	test(b);

	test(1);
	const int d = 1;
	test(std::move(d));
}

执行结果和我们猜想的差别很大, 是因为, 右值引用本身是左值, 所以在模板函数中, 我们传进去的是右值, 但是等到调用f函数的时候, 已经全部是左值了
在这里插入图片描述

5.2完美转发

由上面的例子我们可以看到, 是一个不完美转发, 因为右值失去了它的右值属性, 于是便提出了完美转发, 核心方法是
std::forward, 它在传参过程中, 保留对象原生类型的属性, 我们稍加修改一下上面的例子

void f(int& x)
{
	cout << "左值引用" << endl;
}

void f(const int& x)
{
	cout << "const 左值引用" << endl;
}

void f(int&& x)
{
	cout << "右值引用" << endl;
}

void f(const int&& x)
{
	cout << "const右值引用" << endl;
}

template<typename T>
void test(T&& t)
{
	f(std::forward<T>(t));
}

int main() {
	int a = 1;
	test(a);
	const int b = 1;
	test(b);

	test(1);
	const int d = 1;
	test(std::move(d));
}

执行结果和我们预想的一致了
在这里插入图片描述

总结

右值引用是c++11引入的最重要的新特性之一, 配合着移动语义和完美转发, 是的c++程序运行更加高效.

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

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

相关文章

Pandas实战秘籍:轻松驾驭重复值与异常值的处理艺术,让数据清洗更高效!

1.导包 import numpy as np import pandas as pd2.删除重复行 def make_df(indexs,columns):data [[str(j)str(i) for j in columns] for i in indexs]df pd.DataFrame(datadata,indexindexs,columnscolumns)return df使用 duplicated() 函数检测重复的行 返回元素为布尔类…

昇思MindSpore学习总结二——张量

1、张量 张量tensor表示的是一个多维的矩阵&#xff0c;比如零维就是一个点&#xff0c;一维就是向量&#xff0c;二维就是一般的矩阵&#xff0c;多维就相当于一个多维的数组&#xff0c;这和numpy是对应的&#xff0c;而且PyTorch的Tensor和numpy的ndarray可以相互转换&#…

Android项目框架

Android项目基于Android Studio开发&#xff0c;Android Studio使用Gradle作为项目构建工具。新建工程后可以看到如图所示目录结构&#xff0c;将Android切成Project可以看到完整的Android工程目录结构&#xff0c;如图所示。 图1-2 Android项目目录结构 app目录是一个典型的…

华为OD机试(D卷+C卷+A卷+B卷)2024真题目录(全、新、准)

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、队列4、链表5、栈6、滑动窗口7、二叉树8、并查集9、矩阵 三、算法1、基础算法① 贪心思维② 二分查…

【7】ExternalCommand

文章目录 ExternalCommandProcessComponent(服务端)输入输出 external_command_demo&#xff08;客户端&#xff09;插件ActionCommandProcessor #mermaid-svg-JAXVKwGThGCGDqyK {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#m…

VSCode 插件开发经验小结

理解 vscode&#xff0c;我们首先要谈的是 Electron。 Electron 的核心技术主要包括以下几个方面&#xff1a; Chromium: Electron 使用了 Chromium 浏览器作为其渲染引擎。Chromium 是 Google Chrome 的开源版本&#xff0c;负责处理和渲染应用程序的用户界面&#xff0c;包括…

maketrans()方法——创建字符映射的转换表

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 maketrans()方法用于创建字符映射的转换表&#xff0c;对于接受两个参数的最简单的调用方式&#xff0c;第一个参数是字符串&#xff0c;表…

【Kubernetes】加入节点Node及问题

命令 分别再node节点机器上&#xff0c;执行如下命令&#xff1a; kubeadm join [master机器ip:端口] --token [master机器初始化生成的token] --discovery-token-ca-cent-hash [master机器初始化生成的hash]问题 由于清屏没有记住token和hash的时候&#xff1a; 1&#xff…

外贸企业选择什么网络?

随着全球化的深入发展&#xff0c;越来越多的国内企业将市场拓展到海外。为了确保外贸业务的顺利进行&#xff0c;企业需要建立一个稳定、安全且高速的网络。那么&#xff0c;外贸企业应该选择哪种网络呢&#xff1f;本文将为您详细介绍。 外贸企业应选择什么网络&#xff1f; …

axios的底层ajax,XMLHttpRequest原理解释及使用方法

定义 ajax全称asychronous JavaScript and XML 意思是异步的 JavaScript和xml&#xff0c; 也就是通过javascript创建XMLHttpRequest &#xff08;xhr&#xff09;对象与服务器进行通信 步骤 创建实例对象&#xff0c;初始请求方法和url&#xff0c;设置监听器监听请求完成…

【Rust入门教程】安装Rust

文章目录 前言Rust简介Rust的安装更新与卸载rust更新卸载 总结 前言 在当今的编程世界中&#xff0c;Rust语言以其独特的安全性和高效性吸引了大量开发者的关注。Rust是一种系统编程语言&#xff0c;专注于速度、内存安全和并行性。它具有现代化的特性&#xff0c;同时提供了低…

超简洁Django个人博客系统(适合初学者)

一、环境介绍 Django4.2.13Markdown3.3.4PyMySQL1.1.1Python3.8PyCharm 2023.1.2 (Professional Edition) 二、功能简介 用户登录 通过在pycharm终端执行以下命令创建超级管理员。python manage.py create createsuperuser 创建完成后再通过新建的超级管理员账号进行登录 …

The First项目报告:NvirWorld与区块链游戏的未来

根据官方公告&#xff0c;The Fisrt现货区将于2024年7月2日16:00上架NVIR/USDT交易对&#xff0c;NVIR是NvirWorld平台的原生代币。作为一个去中心化解决方案&#xff0c;NvirWorld为开发者提供了一个简化且适应性强的环境&#xff0c;旨在通过优化的扩展解决方案来降低交易成本…

windows USB设备驱动开发-开发USB 设备端驱动

USB 设备是通过单个端口连接到计算机的外设&#xff0c;例如鼠标设备和键盘。 USB 客户端驱动程序是计算机上安装的软件&#xff0c;该软件与硬件通信以使设备正常运行。 如果设备属于 Microsoft 支持的设备类&#xff0c;Windows 会为该设备加载 Microsoft 提供的 USB 驱动程序…

如何离线安装ctags

首先下载一个ctags源码包&#xff0c;ctags-master.zip&#xff0c;拷贝到ubuntu20中&#xff0c; #unzip ctags-master.zip 找到README文件&#xff0c;找到install的描述&#xff1a; 运行ctags解压后的目录下的autogen.sh 发现缺少autoreconf, autoconf, automake 等一些…

问题集锦1

01.inner中使用JwtTokenUtil.getUserCode() 前端调用上传&#xff08;java&#xff09;&#xff0c;上传使用加购 Overridepublic Boolean insertShoppingCart(InsertShoppingCartParamsDto dto) {// 通过userCode,itemCode和supplierCode来判断当前加购人添加到购物车的商品是…

iminuit,一个神奇的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个神奇的 Python 库 - iminuit。 Github地址&#xff1a;https://github.com/scikit-hep/iminuit 在科学计算和数据分析领域&#xff0c;参数估计和最优化是非常重要的任务。…

【Windows】Visual Studio Installer下载缓慢解决办法

【Windows】Visual Studio Installer下载缓慢解决办法 1.背景2.分析3.结果 1.背景 使用visual studio在线安装包进行IDE安装&#xff0c;发现下载几乎停滞&#xff0c;网速几乎为零。 经过排查并不是因为实际网络带宽导致。 这里涉及DNS知识&#xff1b; DNS&#xff08;Dom…

Python学习速成必备知识,(20道练习题)!

基础题练习 1、打印出1-100之间的所有偶数&#xff1a; for num in range(1, 101):if num % 2 0:print(num) 2、打印出用户输入的字符串的长度&#xff1a; string input("请输入一个字符串&#xff1a;")print("字符串的长度为&#xff1a;", len(str…

【第二周】基础语法学习

目录 前言初始化项目文件介绍基本介绍JSWXMLWXSS 常见组件基础组件视图容器match-mediamovable-area/viewpage-containerscroll-viewswiper 表单组件自定义组件 模板语法数据绑定单向数据绑定双向数据绑定 列表渲染条件渲染模板引用 事件系统事件类型事件绑定阻止冒泡互斥事件事…