当前位置: 首页 > news >正文

C++11中的左右值引用(略带复习)

引子:我们在之前学过,auto(底层为迭代器),范围for,{}初始化(可以省略=),initializer_list,decltype,nullptr(Null字面上为0),arrray(与数组相比,对于出错的处理不同),forward_list(与普通的相比少一点空间),还学过unordered_map与unordered_set(底层为哈希表,详见我前一篇封装)新容器等内容,这些其实是C++11新增的内容,今天我们就来讲一讲另一个C++11的内容——左右值的引用!

一,初解:何为左值,何为右值?

左值(Lvalue)和右值(Rvalue)是表达式的两种分类。

左值指的是可以出现在赋值表达式的左边的表达式,它表示一个对象的身份,即内存地址。

右值则是不能出现在赋值表达式的左边的表达式,它表示一个临时的值或者一个无法获取地址的表达式。

左值引用就是给左值的引用,给左值取别名。----&

右值引用就是对右值的引用,给右值取别名----&&

为什么用&&来右值引用?

我认为:

一,通过使用右值引用,可以确保只有对象的值被移动,而不是对象的引用或指针

二,临时对象通常是右值,它们在表达式中产生并立即被使用。使用&&可以高效地利用这些临时对象,通过移动它们的资源而不是进行复制

举例:左右值:如下

// 左值
int* p = new int(0);
int b = 1;
const int c = 2;
double x = 1.1, y = 2.2;// 右值
10;
x + y;
fmin(x, y);

举例:左右值引用:如下

// 左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;// 右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);

二,再解:左右值引用的转换。

左值引用总结: 1. 左值引用只能引用左值,不能引用右值。 2. 但是const左值引用既可引用左值,也可引用右值

右值引用总结: 1. 右值引用只能右值,不能引用左值。 2. 但是右值引用可以move以后的左值。

move是什么?

其实也不用太复杂!我认为就是一个强转!就是转成右值!

补:其实在底层上,都开了空间,但是在语法上不显示

引用转换:

//左转右
int h ;//左值
int& d = 10;//左值引用,,错误
double& n =x+y;//左值引用,,错误
double& j = fmin(x, y);//左值引用,错误
const int& a = 10;//左值引用
const double& k = x+y;//左值引用
const double&l = fmin(x,y);//左值引用//右转左
int g=10;
int&& t =g;//右值引用,错误
int&& t1 = move(g); //右值引用

如上图错误:

四,后解:右值引用的应用场景与作用!

主要有以下几种:

一,临时对象:例如函数返回的值,它们是右值。

二,移动语义:通过std::move将资源从一个地方移动到另一个地方,避免复制的开销。

移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不 用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己

三,右值引用:允许以右值引用的方式访问右值,这在现代C++编程中用于实现资源的高效转移。

四,完美转发:在模板编程中,完美转发允许将参数以左值或右值的形式传递给其他函数,保持其值类别

我认为右值引用是为了弥补左值引用无法解决传值的问题,可以节省一个拷贝构造!

参考代码:

class Resource {
public:void swap(Resource& s){std::swap(size, s.size);std::swap(data, s.data);}Resource(int size) : size(size), data(new int[size]) {cout << "初始构造" << endl;}// 移动构造函数Resource(Resource&& other) : size(0), data(nullptr) {cout << "移动构造" << endl;swap(other);}// 拷贝构造函数Resource(const Resource& s){cout << "拷贝构造函数" << endl;Resource cmp(s.size);swap(cmp);}// 移动赋值运算符Resource& operator=(Resource&& other){if (this != &other) {cout << "移动赋值运算" << endl;swap(other);}return *this;}// 拷贝赋值运算Resource& operator=(const Resource& s){cout << "拷贝赋值" << endl;Resource cmp(s.size);swap(cmp);}~Resource() {delete[] data;}private:int* data;int size;
};int main() 
{Resource h1(3);Resource h2(h1);Resource h3(move(h1));Resource h4 =move(h2);return 0;
}

补:其实右值引用的本质上还是左值!

五,万能的转发(补)

万能的转发是指在模板函数中使用std::forward来转发参数,它可以保持参数的原始值类别(左值或右值)。这在模板编程中非常有用,因为它允许函数模板接受不同类型的参数,并将这些参数以它们原始的值类别传递给其他函数

测试代码:

void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }/*引用传左值->左值引用传右值->右值引用*/
template<typename T>
void PerfectForward(T&& t)
{// 模版实例化是左值引用,保持属性直接传参给Fun// 模版实例化是右值引用,右值引用属性会退化成左值,转换成右值属性再传参给FunFun(forward<T>(t));
}int main()
{PerfectForward(10);           // 右值int a;PerfectForward(a);            // 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b);			  // const 左值PerfectForward(std::move(b)); // const 右值return 0;
}

结果:

下集:我们进入可变参数的摸板分享!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PyTorch 基础学习(1) - 快速入门
  • 从零开始搭建 LVS 高性能集群 (DR模式)
  • JAVA中的对象流ObjectInputStream
  • uniapp实现自定义弹窗组件,支持富文本传入内容
  • Linux:Linux环境基础开发工具使用
  • DIAdem 与 LabVIEW
  • 【数据结构篇】~顺序表
  • Golang | Leetcode Golang题解之第336题回文对
  • 分布式锁实现方案--redis、zookeeper、mysql
  • Java从zip文件中读取指定的csv文件使用EasyExcel解析出现流关闭异常Stream closed
  • 【常见算法题】斐波那契数列(矩阵快速幂)
  • 歌曲爬虫下载
  • java多线程(初阶)
  • 【Godot4自学手册】第四十五节用着色器(shader)制作水中效果
  • linux C语言remove函数及相关函数
  • [笔记] php常见简单功能及函数
  • ES2017异步函数现已正式可用
  • hadoop集群管理系统搭建规划说明
  • JavaScript 基础知识 - 入门篇(一)
  • Nacos系列:Nacos的Java SDK使用
  • Vue 动态创建 component
  • 大快搜索数据爬虫技术实例安装教学篇
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 欢迎参加第二届中国游戏开发者大会
  • 那些被忽略的 JavaScript 数组方法细节
  • 批量截取pdf文件
  • 前端学习笔记之观察者模式
  • 日剧·日综资源集合(建议收藏)
  • 入门级的git使用指北
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 一、python与pycharm的安装
  • Mac 上flink的安装与启动
  • # include “ “ 和 # include < >两者的区别
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #nginx配置案例
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (二)构建dubbo分布式平台-平台功能导图
  • (二开)Flink 修改源码拓展 SQL 语法
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (数据结构)顺序表的定义
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转) Android中ViewStub组件使用
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • .NET MVC第三章、三种传值方式
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .Net Web项目创建比较不错的参考文章
  • .net生成的类,跨工程调用显示注释