左值引用与右值引用的区别?右值引用的意义?

news2024/9/28 15:32:13

左值引用与右值引用的区别?右值引用的意义?

  • 1 区别
    • 1.1 功能差异
      • 1.2 左值引用
      • 1.3 右值引用
        • 1.3.1 实现移动语义
        • 1.3.2 实现完美转发
  • 2 引用的作用
  • 3 区分左值和右值
    • 3.1 左值
    • 3.2 右值

1 区别

左值引用是对左值的引用;右值引用是对右值的引用。

(1)使左值指向右值

const 左值引用能指向右值,局限是不能修改这个值。

注意:使用const不能修改值时,可以使用引用,引用该值并对其进行修改。

(2)使右值指向左值

右值引用通过**std::move(v)**可以将左值转化为右值,此时右值就是将亡值。

(3)声明出来的左值引用或右值引用都是左值

int i=0;

//引用是必须初始化
//此时的j引用的是右值'100'
int && j=100; //右值引用  

int & k=i;//左值引用

1.1 功能差异

1.2 左值引用

避免对象拷贝。

  • 函数传参
  • 函数返回值

1.3 右值引用

1.3.1 实现移动语义

解决对象赋值的问题,避免资源(堆上)的重新分配。有深拷贝的情况下。

以数据库举例。

以前:与数据库创建连接,不想把连接对象关闭,需要再创建另一个连接,再把连接资源拿过来。

现在:直接把连接对象的资源拿给另一个对象是用,就不用再创建并删除一个与数据库之间的连接对象。

以文件举例。

以前:一个文件描述fd,按照以前的深拷贝需要重新打开一个文件。

现在:直接把该文件资源fd移动到另外一个对象中就可以了。

拷贝赋值构造与拷贝构造:

//拷贝赋值构造 深拷贝(资源的重新分配)
A a1,b1;
a1=b1; 

//拷贝构造 深拷贝
A a2;
A b2(a2);//当前a2是左值
cout<<"b,p="<<b.p<<endl;//输出结果:b,p=A(const A&)...

A b2(std::move(a2));//改为右值
cout<<"b,p="<<b.p<<endl;//输出结果:b,p=A(A&&)...

深拷贝与浅拷贝:

//深拷贝
A(const A&a)//拷贝构造
{
    //拷贝构造中使用的是const,只能读,不能写,所以不能再拷贝构造中使用移动构造进行资源转移
	p=new int(10);
    memcpy(p,a.p,10*sizeof(int));//重新分配内存
    cout<<"A(const A&):p="<<p<<endl;
}

//浅拷贝
A(A&& a) //移动构造
{
   //直接把a上的资源赋值给自己,并把a中的资源置空
    this->p=a.p;
    a.p=nullptr;
    cout<<"A(A&&)"<<endl;
}

stl中的应用:

list<A> alist;
alist.push_back(A());//当前A()为右值
auto &ele=alist.front();//取出第一个值
cout<<"ele.p="<<ele.p<<endl;//输出结果:ele.p=A(A&&)...

1.3.2 实现完美转发

定义:函数模板可以将自己的参数完美地转发给内部调用的其他函数。

完美指的是不仅能准确地转发参数的值,还能保证转发的参数的左右值属性不变。使用std::forward(v)实现。

//左值
void func(int &n)
{
    cout<<"left value="<<n<<endl;
}

//右值
void func(int &&n)
{
    cout<<"right value="<<n<<endl;
}

//调用函数进行转发

//c11以前 
template<template T>
void revoke(T &t)
{
    //此时的t唯一个具体的值
    func(t);//只能转发左值,调用的函数为func(int &n)
}

//c11以前,如果一定要转发右值
void revoke(const T &t)
{
    func(t);//但是不能对t进行修改
}

/**************分割线***************/

//c11 完美转发
template<template T>
void revoke(T &&t)//T &&t为万能引用
{
    func(std::forward<T>(t));
}

万能引用:具有模板参数或者模板推导的叫做万能引用。

1)具有模板参数:

template<typename T>
void  tempFun(T&& t) {}  //模板类型的这种用法 T && 是万能引用最常见的使用场合

2)具有模板推导:

auto&& var2 = var1;  //auto这种需要推断类型的地方

万能引用虽然跟右值引用的形式一样,但右值引用需要是确定的类型,如: int && ref = x;就是右值引用。

借用万能引用的方式接受左右属性的值。使用引用折叠规则实现。

template<template T>
void revoke(T &&t)//T &&t为万能引用
{
    func(std::forward<T>(t));
}

int main()
{
    int i=10;
	revoke(10);//右值  万能引用中会转换成int && t
    revoke(i);//左值 万能引用中会转换成int & t
    
     return 0;
}

引用折叠规则

1)参数为左值或左值引用,T&&将转化为int &

2)参数为右值或右值引用,T&&将转化为int &&
在这里插入图片描述
在这里插入图片描述

注意:万能引用只接收值,void revoke(T &&t)中的t仍然是左值!

std::forward(v):

1)T为左值引用,v将转化为T类型的左值。

2)T为右值引用,v将转化为T类型的右值。

int main()
{
    int i=10;
    int &m=i;
    int &&n=100;
    
    //不使用类型强制转换,会直接到调用左值void func(int &n)
    remoke(m);
    remoke(n);
    
    //使用类型强制转换
    remoke(static_cast<int&>(m));
    remoke(static_cast<int&&>(n));
    
    return 0;
}

2 引用的作用

(1)别名,没有地址

(2)声明时必须要初始化

(3)通过引用修改变量值

3 区分左值和右值

3.1 左值

可以在等号左边,能够取地址,具名

举例:

1)变量名

2)返回左值引用的函数调用

3)前置自增/自减

int i=0;
++i=10;//++i为左值
cout<<i<<endl;  //输出结果:10

4)赋值运算/复合赋值运算

int i=0;
//赋值运算
(i=9)=100;
cout<<i<<endl;//输出结果:100

//复合赋值运算
(i+=10)=1000;
cout<<i<<endl;//输出结果:1000

5)解引用

A *a=new A;
*a=...

6)…

3.2 右值

只能在等号右边,不能取地址,不具名

  • 纯右值

    举例:

    1)字面值

    2)返回非引用类型和函数调用

    3)后置自增/自减

    int a=0;
    i++=100;//error 纯右值不能作为左值
    i++;//正确写法
    

    4)算术表达式:+*/

    5)逻辑表达式:^&|~

    6)比较表达式:><=

    7)…

  • 将亡值:c++11新引入的与右值引用(移动语义)相关的值类型

    定义:将亡值用来触发移动构造或移动赋值构造,并进行资源转移,之后将调用析构函数

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

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

相关文章

【Linux】进程通信 — 共享内存

文章目录 &#x1f4d6; 前言1. 共享内存2. 创建共享内存2.1 ftok()创建key值&#xff1a;2.2 shmget()创建共享内存&#xff1a;2.3 ipcs指令&#xff1a;2.4 shmctl()接口&#xff1a;2.5 shmat()/shmdt()接口:2.6 共享内存没有访问控制&#xff1a;2.7 通过管道对共享内存进…

实验六 调度器-实验部分

目录 一、知识点 1.进程调度器设计的目标 1.1.进程的生命周期 1.2.用户进程创建与内核进程创建 1.3.进程调度器的设计目标 2.ucore 调度器框架 2.1.调度初始化 2.2.调度过程 2.2.1.调度整体流程 2.2.2.设计考虑要点 2.2.3.数据结构 2.2.4.调度框架应与调度算法无关…

二十三章:抗对抗性操纵的弱监督和半监督语义分割的属性解释

0.摘要 弱监督语义分割从分类器中生成像素级定位&#xff0c;但往往会限制其关注目标对象的一个小的区域。AdvCAM是一种图像的属性图&#xff0c;通过增加分类分数来进行操作。这种操作以反对抗的方式实现&#xff0c;沿着像素梯度的相反方向扰动图像。它迫使最初被认为不具有区…

【已解决】电脑连上网线但无法上网

文章目录 案例情况解决方案必要的解决方法简要概括详细步骤1、打开控制面板2、打开更改适配器设置3、 找Internet协议版本44、修改配置 可能有用的解决方法 问题解决原理Internet 协议版本 4&#xff08;TCP/IPv4&#xff09;确保IP地址和DNS服务器设置为自动获取 案例情况 网…

Knowledge-QA-LLM: 基于本地知识库+LLM的开源问答系统

⚠️注意&#xff1a;后续更新&#xff0c;请移步README Knowledge QA LLM 基于本地知识库LLM的问答系统。该项目的思路是由langchain-ChatGLM启发而来。缘由&#xff1a; 之前使用过这个项目&#xff0c;感觉不是太灵活&#xff0c;部署不太友好。借鉴如何用大语言模型构建一…

CTF学习路线指南(附刷题练习网址)

前言&#xff1a; PWN,Reverse&#xff1a;偏重对汇编&#xff0c;逆向的理解&#xff1b; Gypto&#xff1a;偏重对数学&#xff0c;算法的深入学习&#xff1b; Web&#xff1a;偏重对技巧沉淀&#xff0c;快速搜索能力的挑战&#xff1b; Mic&#xff1a;则更为复杂&…

devDept Eyeshot 2024 预告-Update-Crack

即将发布的版本 开发商在一个动态的环境中运作&#xff0c;事情可能会发生变化。本页提供的信息旨在概述 devDept 软件产品的总体方向。它仅供参考&#xff0c;不应作为做出任何决定性的依据。devDept Eyeshot 2024软件产品描述的任何特性或功能的开发、发布和时间安排仍由 dev…

css实现渐变边框动画

渐变边框动画 1、实现效果2、实现代码 1、实现效果 2、实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&…

Hexo的Fluid主题中自定义iconfont图标

Hexo的Fluid主题介绍 Hexo是一个快速、简洁且高效的博客框架。 Hexo使用Markdown&#xff08;或其他标记语言&#xff09;解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 Fluid是Hexo中一个优雅的主题&#xff0c;这是一款Material Design风格的He…

提取渥太华大学机械故障敏感特征,再利用决策树分类(Python代码)

该数据集是从渥太华大学采集的轴承振动信号&#xff0c;这些信号是在时间变化的转速条件下收集的。数据集包含4个不同引擎的每个引擎的12秒信号数据。采样频率为10000 代码主要流程&#xff1a; 数据导入与预处理&#xff1a; 通过scipy.io.loadmat()函数从"dataset.mat&q…

docker配置文件挂载(容器数据管理)

目录 数据卷&#xff08;容器数据管理&#xff09;什么是数据卷数据集操作命令创建和查看数据卷挂载数据卷案例案例-给nginx挂载数据卷案例-给MySQL挂载本地目录 总结 数据卷&#xff08;容器数据管理&#xff09; 在之前的nginx案例中&#xff0c;修改nginx的html页面时&#…

教雅川学缠论05-线段

线段需要满足下面4个条件&#xff1a; 1.是由3条笔&#xff0c;或者3条以上组成&#xff0c;同笔一样&#xff0c;线段也是有方向的 2.如果线段起始于向上笔&#xff0c;则终止与向上笔&#xff08;一定不会终止与向下笔&#xff09; 3.如果线段起始于向下笔&#xff0c;则终止…

Python接口自动化测试框架运行原理及流程

这篇文章主要介绍了Python接口自动化测试框架运行原理及流程,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 本文总结分享介绍接口测试框架开发&#xff0c;环境使用python3selenium3unittestddtrequests测试框…

Themis 国库建设计划启动,开启去中心化新征程

在未来的金融领域&#xff0c;去中心化金融&#xff08;DeFi&#xff09;正在成为一种重要的趋势。在这股DeFi热潮中&#xff0c;作为Filecoin 生态下的一颗璀璨明珠&#xff0c;Themis 上线仅2个月&#xff0c;多项数据便稳居Filecoin-FVM榜首&#xff0c;TVL更是牢牢处于File…

wxWidgets 打开文件对话框wxFileDialog

wxFileDialog dialog(this, _("Open file"), wxEmptyString, wxEmptyString); if (dialog.ShowModal() wxID_OK) { wxString strPath dialog.GetPath(); } 效果图&#xff1a;

小莫计数摸高训练器:让孩子健康成长的好帮手

现在孩子们的生活方式越来越单一&#xff0c;很多孩子缺乏运动&#xff0c;喜欢在手机上看视频、玩游戏&#xff0c;导致身体素质下降。为了让孩子更好地锻炼身体&#xff0c;我最近入手了一款小莫计数摸高训练器&#xff0c;这是个很实用的儿童锻炼辅助器。 小莫计数摸高训练器…

【JAVASE】循环结构

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈Java &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 循环 1. 循环结构1.1 while 循环1.2 bre…

无涯教程-jQuery - Scale方法函数

Scale 效果可以与show/hide/toggle一起使用。这会使元素缩小或增长一个百分比因子。 Scale - 语法 selector.hide|show|toggle( "scale", {arguments}, speed ); 这是所有参数的描述- direction - 方向。可以是"both"&#xff0c;"垂…

【UE5】快速认识入门

目录 &#x1f31f;1. 快速安装&#x1f31f;2. 简单快捷键操作&#x1f31f;3. 切换默认的打开场景&#x1f31f;4. 虚幻引擎术语 &#x1f31f;1. 快速安装 进入Unreal Engine 5官网进行下载即可&#xff1a;UE5 &#x1f4dd;官方帮助文档 打开后在启动器里创建5.2.1引擎…

Optitrack下飞控刷px4固件并进行参数配置(视觉vision定位适用)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一:寻找固件二&#xff1a;QGC配置参数2.1&#xff1a;飞控初始化配置2.2&#xff1a;利用视觉定位作为位置反馈 三&#xff1a;PID调试/飞行日志查看 前言 参…