C++之左值、右值、完美转发

1、左值、右值概念

左值:
        是指在内存中有明确的地址,可以进行取地址操作。

// 以下的a、p、*p、b都是左值
int a = 3;
int* p = &a;
*p;
const int b = 2;

右值:
        只提供数据,无法进行取地址操作。

double x = 1.3, y = 3.8;
// 以下几个都是常见的右值
10;                // 字面常量
x + y;             // 表达式返回值
fmin(x, y);        // 传值返回函数的返回值

注意:

        所有有名字的都是左值,而右值是匿名的。
        一般情况下,位于等号左边的是左值,位于等号右边的是右值,但是也可以出现左值给左值赋值的情况。

2、左值引用、右值引用 

左值引用:

        需要引用一个有名字的变量,不能引用不具名的对象。

// 以下几个是对上面左值的左值引用
int& ra = a;
int*& rp = p;
int& r = *p;
const int& rb = b;

右值引用:

        只能引用字面常量,不具有名字。

        C++11新引入了右值引用,记作“&&”。

// 以下几个是对上面右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);

注意:

左值引用:

        (1)左值引用只能引用左值,不能直接引用右值。

        (2)但是const左值引用既可以引用左值,也可以引用右值。

左值引用使用场景:

        (1)做函数参数。

        (2)做函数返回值。【当返回对象出了函数作用域以后仍然存在时,可以使用左值引用返回;当返回对象(对象是函数内的局部对象)出了函数作用域以后不存在时,不能使用左值引用。】

右值引用:

        (1)右值引用只能引用右值,不能直接引用左值。

        (2)但是右值引用可以引用被move的左值。

右值引用使用场景:

        (1)移动语义。【std::move()】。

        (2)C++11标准的STL 容器的相关接口函数也增加了右值引用版本。【vectoe::push_back、vector::insert、vector::operator=、map::insert、list::push_back】。

        (3)完美转发。

代码:

#include <iostream>int main()
{int x = 10;int y = 20;/**************************** 左值引用 ****************************/// 左值引用只能引用左值int t = 8;       // t是左值int& t1 = t;     // t1是左值//int& t2 = 8;   // 编译报错,因为8是右值,不能直接引用右值// const左值引用既可以引用左值const int& t3 = t;         // t3是左值,t也是左值const int& t4 = 8;         // t4是左值,也可以引用右值const double& r1 = x + y;/**************************** 右值引用 ****************************/// 右值引用只能引用右值int&& r1 = 10;double&& r2 = x + y;const double&& r3 = x + y;int t = 10;//int&& r4 = t;        // 编译报错,不能直接引用左值int *p = &t;// 右值引用可以引用被move的左值int&& r5 = std::move(t);int*&& r6 = std::move(p);int&& r7 = std::move(*p);return 0;
}

结果:

 

3、引用折叠

         C++中,并不是所有情况下 && 都代表右值引用,在模板和自动类型推导(auto)中,如果是模板参数,想要指定为 T&&,如果是自动类型推导,需要指定为 auto&&,这两种情况下,&& 被称作“未定的引用类型”。

        另外 const T&& 表示一个右值引用,不是未定引用类型。

template<typename T>
void fun(T&& param)
{work(forward<T>param)
}
int main()
{fun(10);  //对于 f(10) 来说传入的实参 10 是右值,因此 T&& 表示右值引用int x = 1;fun(x);   //对于 f(x) 来说传入的实参是 x 是左值,因此 T&& 表示左值引用return 0;
}

        因为 T&& 或者 auto&& 这种未定引用类型作为参数时,有可能被推导成右值引用,也有可能被推导为左值引用,在进行类型推导时,右值引用会发生变化,这种变化被称作引用折叠。折叠规则如下:

        (1)提供右值推导 T&& 或者 auto&& 得到的是一个右值引用类型,const T&& 表示一个右值引用。
        (2)通过非右值(右值引用、左值、左值引用、常量右值引用、常量左值引用)推导 T&& 绘制 auto&& 得到的是一个左值引用类型。

int main()
{int&& a1 = 1;			//右值   ----   右值引用auto&& bb = a1;			//右值引用   ----   左值引用auto&& bb1 = 2;			//右值   ----   右值引用int a2 = 1;int& a3 = a2;			//左值   ----   左值引用auto&& cc = a3;			//左值引用   ----   左值引用auto&& cc1 = a2;		//左值   ----   左值引用const int& s1 = 1;		//常量左值引用const int&& s2 = 1;		//常量右值引用auto&& dd = s1;			//常量左值引用   ----   左值引用auto&& ee = s2;			//常量右值引用   ----   左值引用return 0;}

4、std::forward()

完美转发:

        一个函数或类模板可以将其参数原封不动地转发给另一个函数或类模板,同时保持被转发参数的左右值特性(lvalue 或 rvalue)。

std::forward:

        C++11 引入的模板函数,其主要作用是在模板函数或模板类中,将一个参数以“原样”的方式转发给另一个函数,该函数被用于实现完美转发。

        在 C++ 中,函数参数可以是左值引用,也可以是右值引用。对于一个模板函数或类模板,当传递一个参数时,如果该参数是左值,那么传递的就是一个左值引用;如果该参数是右值,那么传递的就是一个右值引用。

代码:

#include <iostream>void func(int& x) {std::cout << "lvalue reference: " << x << std::endl;
}void func(int&& x) {std::cout << "rvalue reference: " << x << std::endl;
}// 模板函数
template<typename T>
void Box(T&& arg) {func(std::forward<T>(arg));
}int main() {int x = 42;// 调用模板函数,传入参数x,是一个左值;调用了左值的打印函数;Box(x);// 调用模板函数,传入参数1,是一个右值;调用了右值的打印函数;Box(1);return 0;
}

结果:

lvalue reference: 42
rvalue reference: 1

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

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

相关文章

如何将云服务器上操作系统由centos切换为ubuntu

本文将介绍如何将我们购买的云服务器上之前装的centos切换为ubuntu&#xff0c;云服务器以华为云为例&#xff0c;要切换的ubuntu版本为ubuntu20.04。 参考官方文档&#xff1a;切换操作系统_弹性云服务器 ECS (huaweicloud.com) 首先打开华为云官网&#xff0c;登录后点击右…

frm一级4个1大神复习经验分享系列(二)

先说一下自己的情况&#xff0c;8月份中旬开始备考&#xff0c;中间一直是跟着网课走&#xff0c;notes和官方书都没看&#xff0c;然后10月份下旬开始刷题一直到考试。下面分享一些自己备考的经验和走过的弯路。 一级 一级整体学习下来的感受是偏重于基础的理论知识。FRM一级侧…

MongoDB分片集群容灾方案

MongoDB分片集群容灾方案 1. 集群同步工具介绍1.1 第三方数据同步工具mongoshake1.2 官方同步工具mongosync 2. 工具对比2.1 数据一致性2.2 稳定性和可靠性2.3 维护成本 3. 总结 1. 集群同步工具介绍 最近客户咨询MongoDB分片集群市面上主流的容灾方案&#xff0c;所以抽空整理…

Java | String类型使用注意事项

String不支持下标访问&#xff01; String s1"wgh";中&#xff0c;创建了一个String对象&#xff08;此语句等效为String s1new String("wgh")&#xff09;。直接用字符串字面量构造的字符串在常量池里&#xff1b;用new String方法构造的字符串在堆里。 …

安卓六种页面加载优化方案对比总结

根据工作经验&#xff0c;笔者提炼了六种页面加载优化方式&#xff0c;按照业务与非业务&#xff0c;将六种加载方式分为两类&#xff1a; 业务类 控制业务与UI的执行顺序、控制多业务之间的执行顺序 ①预加载&#xff1a;是指在进入页面之前&#xff0c;提前获得页面所需得数据…

Conda入门教程

Conda是一个强大的开源包和环境管理系统&#xff0c;专为Python设计&#xff0c;但也可以用于其他语言。以下是Conda的入门教程&#xff0c;帮助你开始使用Conda进行Python环境和包的管理。 一、安装Conda 访问Conda的官网&#xff08;https://conda.io/projects/conda/en/la…

操作系统 - 计算机系统概述

事前提一嘴 室友考完研了&#xff0c;下一年就是我了&#xff0c;真不想和他们一起考&#xff0c;压力太大了&#xff0c;这里分享一点笔记吧 采用王道考研的书以及视频&#xff0c;去掉了一些书上的废话&#xff0c;加上了视频中的重点&#xff0c;最后总结出来的 如有侵权&a…

直播预告|中服云第5代`工业物联产品线上发布会

我国作为全球制造业的领军者&#xff0c;拥有世界上最完整且健全的制造业产业链。但随着各企业规模的扩大和设备的增加&#xff0c;企业设备管理面临的难点和挑战也越来越多。 为了满足企业不断提高的设备管理需求&#xff0c;中服云即将推出全新的“设备全生命周期管理系统5.…

SOA 与“微服务”的区别

SOA&#xff08;面向服务的架构&#xff09;与微服务之间的区别可以从多个维度进行分析。以下是一些主要的区别点&#xff1a; 服务粒度&#xff1a; SOA&#xff1a;服务粒度相对较粗。在SOA中&#xff0c;服务可能涵盖多个功能或业务领域&#xff0c;例如&#xff0c;在一个大…

机器学习之聚类学习

聚类算法 概念 根据样本之间相似性&#xff0c;将样本划分到不同类别种&#xff0c;不同相似度计算方法&#xff0c;会得到不同聚类结果&#xff0c;常用相似度计算方法为&#xff1a;欧氏距离 目的是在没有先验知识情况下&#xff0c;自动发现数据集种内在结构和模式 无监督…

告别裸奔,聊聊主流消息队列的认证和鉴权!

大家好&#xff0c;我是君哥。 我们在使用消息队列时&#xff0c;经常关注的是消息队列收发消息的功能。但好多时候需要对客户端有一定的限制&#xff0c;比如只有持有令牌的客户端才能访问集权&#xff0c;不允许 Producer 发送消息到某一个 Topic&#xff0c;或者某一个 Top…

朗之万动力学(Langevin dynamics)

朗之万动力学&#xff08;Langevin dynamics&#xff09; 是一种模拟经典粒子运动的方法&#xff0c;常用于物理、化学和材料科学等领域。它是由法国物理学家保罗朗之万&#xff08;Paul Langevin&#xff09;于1908年提出的&#xff0c;用于描述布朗运动&#xff0c;即微小粒…

四、通信和网络安全—局域网|广域网|远程连接和攻击技术(CISSP)

目录 1.局域网和广域网 1.1 WAN技术总结 2.远程连接—无线技术 2.1 VPN 2.2 隧道协议总结

人脸识别——Webface-OCC遮挡人脸识别算法解析

1. 概述 自2019年被誉为人脸识别技术的元年&#xff0c;各地纷纷引入这项技术。然而&#xff0c;自2020年起&#xff0c;为了抵御冠状病毒&#xff08;COVID-19&#xff09;的全球传播&#xff0c;人们普遍开始佩戴口罩。众所周知&#xff0c;现有人脸识别模型在面对遮挡物&am…

Dalle2学习

Dalle2 mini有GitHub库并且有网页可以直接测试

网络之再谈体系结构

大家都知道的是网络的体系结构&#xff0c;现代软件常用的体系结构无非是TCP/IP协议栈&#xff0c;OSI因为实现复杂并且效率没有TCP/IP协议栈好&#xff0c;所以不用OSI&#xff0c;但是&#xff0c;最近在复习网络知识的时候&#xff0c;发现了一些奇怪的地方&#xff0c;那就…

C/C++连接MySQL

本章Gitee仓库地址&#xff1a;mysql连接基本操作 文章目录 1. mysql connect库2. mysql相关接口2.1 mysql_init()2.2 mysql_real_connect()2.3 mysql_query()2.4 mysql_store_result()2.41 mysql_num_rows2.42 mysql_num_fields2.43 mysql_fetch_row2.44 mysql_fetch_fields 2…

中国上市企业行业异质性数据分析

数据简介&#xff1a;企业行业异质性数据是指不同行业的企业在运营、管理、财务等方面的差异性数据。这些数据可以反映不同行业企业的特点、优势和劣势&#xff0c;以及行业间的异质性对企业经营和投资的影响。通过对企业行业异质性数据的分析&#xff0c;投资者可以更好地了解…

STM32系列-STM32介绍

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” STM32介绍 STM32介绍 ST&#xff1a;指的是意法半导体 M&#xff1a;指定微处理器 32&#xff1a;表示计算机处理器位数 ARM分成三个系列&#xff1a; Cortex-A&#xff1…

Python读取Excel表格文件并绘制多列数据的曲线图

本文介绍基于Python语言&#xff0c;读取Excel表格数据&#xff0c;并基于给定的行数范围内的指定列数据&#xff0c;绘制多条曲线图&#xff0c;并动态调整图片长度的方法。 首先&#xff0c;我们来明确一下本文的需求。现有一个.csv格式的Excel表格文件&#xff0c;其第一列为…