C++11左值、右值

知识回顾,详解引用

简单概括,引用就是给已存在对象取别名,引用变量与其引用实体共用同一块内存空间

左右值区分

注意:不一定=左边的都是左值,=右边的都是右值

=左边的也可能是右值,等号右边的也可能是左值

int main()
{int a = 10;int b = 20;// a和b都是左值,b既可以在=的左侧,也可在右侧,// 说明:左值既可放在=的左侧,也可放在=的右侧a = b;b = a;const int c = 30;// 编译失败,c为const常量,只读不允许被修改//c = a;// 因为可以对c取地址,因此c严格来说不算是左值cout << &c << endl;// 编译失败:因为b+1返回的是一个临时变量,没有具体名称,也不能取地址,因此为右值//b + 1 = 20;//b+1会调用编译器自己的operator+这个函数,然后返回结果会返回一个临时对象return 0;
}

C++11对右值进行了严格的区分:

1.C语言中的纯右值,比如:a+b, 100,a+b返回的是一个临时对象,不能对该对象取地址,所以为右值

2.将亡值。比如:表达式的中间结果、函数按照值的方式进行返回。

3.const修饰的常量,不可修改,只读类型的,理论应该按照右值对待,但因为其可以取地址(如果只是 const类型常量的定义,编译器不给其开辟空间,如果对该常量取地址时,编译器才为其开辟空间), C++11认为其是左值。

右值引用

int main()
{//reference引用ra=reference_aint a = 1;int& ra1 = a;//=不表达赋值,仅表示将a变量所代表的空间重新起了一个ra的别名//cout << &1 << endl;//错误--提示表达式必须为左值//cout << &a << endl;//正确--区分&1,a是将1的值赋值给a,a已经开辟了空间,a为左值//1为右值(纯右值),不能对1取地址,简单理解为。//int& ra2 = 1;//没有地址就没有可操作空间没有空间就不能对该空间起别名//右值引用--&&//由于右值都没有具体空间,根据引用特性,对同一块空间取别名//我们必须创造一个空间,并将右值传递到该空间,才能使用右值引用int&& r1 = 1;//1赋值给一个临时空间,r1实际是对该临时空间的引用r1 = 2;//有了空间后就能修改cout << r1 << endl;//int&& r2 = a;//报错--无法将右值引用绑定到左值(右值引用不能引用左值)return 0;
}

const引用

int main()
{int a = 1;//const左值引用const int& ra1 = a;//const右值引用const int&& ra2 = 1;return 0;
}

const可以对右值引用也可以对左值引用

右值引用作用

C++11中右值引用主要有以下作用:

1. 实现移动语义(移动构造与移动赋值)

移动构造:

string& operator=(string&& s)
{swap(s);//对象里的变量和s(临时对象)内容交换后,将老版本内容随着s的生命周期的消失而deletereturn *this//返回对象
}

移动赋值:

String(String&& s): _str(s._str)
{s._str = nullptr;
}

2. 给中间临时变量取别名(提高效率节省资源,对于开空间的自定义类)

左右值引用后修改值

int main()
{int a = 1;cout << "引用前a的值" << a << endl;//左值引用int& ra1 = a;ra1 = 2;cout << "引用修改后a的值" << ra1 << endl;//右值引用int&& ra2 = 1;cout << "引用前a的值" << ra2 << endl;ra2 = 3;cout << "引用修改后a的值" << ra2 << endl;//这里表明:右值(1)被右值引用(ra2)后的属性是左值ra2 = 3return 0;
}

为什么右值被右值引用后引用变量的属性是左值?

答:在被右值引用后会为右值创建一个临时变量≈创建了一个实际的存储空间。所以最后引用变量的属性是左值。

右值引用后引用变量的属性是左值

class String
{
public://有参构造String(const char* str = ""){if (nullptr == str)str = "";_str = new char[strlen(str) + 1];strcpy(_str, str);}//拷贝构造String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}//嵌套多个函数模拟实验右值在传递后的属性String copy(const String& s){_str = new char[strlen(s._str) + 1];strcpy(_str, s._str);cout << "传递来的str_left_value为左值" << endl;return *this;}void class_copy(String&& str_left_value)//str_left_value记为str1{copy(str_left_value);//str_left_value记为str2}//移动语义-移动构造String(String&& s): _str(s._str){s._str = nullptr;}~String(){if (_str) delete[] _str;}
private:char* _str;
};int main()
{String str;str.class_copy("abc");return 0;
}

图解:

因为此时还是对数组类型进行操作,不断的复制已有内容会造成资源的浪费,我们依旧还想用右值引用来减少浪费

class String
{
public://有参构造String(const char* str = ""){if (nullptr == str)str = "";_str = new char[strlen(str) + 1];strcpy(_str, str);}//拷贝构造String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}//仅测试void copy(String& s){cout << "传递来的str_left_value为左值" << endl;}void copy(String&& s){cout << "传递来的str_left_value为右值" << endl;}//右值引用后继续使用右值void class_copy(String&& str_left_value){copy(move(str_left_value));}//移动语义-移动构造String(String&& s): _str(s._str){s._str = nullptr;}~String(){if (_str) delete[] _str;}
private:char* _str;
};int main()
{String str;str.class_copy("abc");return 0;
}

此时只要我们将右值引用后引用变量的属性是左值让其move后转变成右值就可以继续使用右值引用

注意:为了避免const修饰右值引用导致资源无法转移,在以后使用右值引用转移资源时应避免或禁止使用const

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

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

相关文章

Linux C语言:函数的基本用法及传参

一、函数的基本用法 1、main函数 int main(int argc, const char * argv[]) { printf("Hello world\n"); return 0; }数据类型 函数名称 (参数) { //.... return 表达式 } 2、函数 函数是一个完成特定功能的代码模块&#xff0c;其程序代码独立&#xff0c;通常要…

Java注解@Transa1ctional失效特殊情况

最近接手了一个项目需要在上面新加一个模块&#xff0c;我这边直接把之前的模块复制一份改改&#xff0c;去掉多余的文件就开始写了&#xff0c;但是就在一小时前&#xff0c;我调试接口的时候突然就发现事务回滚失效了&#xff0c;准确的说是事务都没有正常开启&#xff0c;这…

Linux vim 文本编辑 操作文本 三种模式

介绍 vi 是一个经典的行编辑器&#xff0c;支持模式编辑&#xff08;包括普通模式、插入模式和命令模式&#xff09;。 vim 保留vi核心功能的基础上&#xff0c;增加了多级撤销、语法高亮、插件支持等高级功能。 两者的最大区别&#xff0c;简单的来说vim就是vi的增强版 三…

Kafka生产者消息发送流程原理及源码分析

Kafka是一个分布式流处理平台,它能够以极高的吞吐量处理数据。在Kafka中,生产者负责将消息发送到Kafka集群,而消费者则负责从Kafka集群中读取消息。本文将探讨Kafka生产者消息发送流程的细节,包括消息的序列化、分区分配、记录提交等关键步骤。 先看一个生产者发送消息的代…

LaDM3IL:多实例学习用于免疫库分类

一个人的免疫组库由某一时间点的大量适应性免疫受体组成&#xff0c;代表了该个体的适应性免疫状态。免疫组库分类和相关受体识别有可能为新型疫苗的开发做出贡献。大量的实例对免疫组库分类提出了挑战&#xff0c;这可以表述为大规模多实例学习 (MMIL&#xff0c;Massive Mult…

pdf.js实现web h5预览pdf文件(兼容低版本浏览器)

注意 使用的是pdf.js 版本为 v2.16.105。因为新版本 兼容性不太好&#xff0c;部分手机预览不了&#xff0c;所以采用v2版本。 相关依赖 "canvas": "^2.11.2", "pdfjs-dist": "^2.16.105", "core-js-pure": "^3.37.…

苹果新型基于home app的骚扰

近期很多用户收到了新型骚扰信息&#xff0c;通过「家庭」邀请。 故障回显&#xff1a; 你会有到一条邀请你加入 Apple 智能家庭的邀请信息&#xff0c;但邀请信息的内容是骚扰信息&#xff0c;且骚扰信息中通常携带链接&#xff0c;千万不要随意打开。 这种骚扰方式暂时没有…

通信协议—Modbus

1、modbus简介 Modbus服务器&#xff1a;接收处理来自客户端的请求&#xff0c;并返回相应的响应&#xff1b; Modbus客户端&#xff1a;向Modbus服务器发送请求&#xff0c;并接收服务器返回的响应的设备或程序&#xff1b; 2、modbus poll调试工具下载 modbus poll用于测…

Python基础教程(二十):SMTP发送邮件

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

【C语言】assert.h——断言

文章目录 主要内容调试和发布模式使用示例用法总结与注意事项 断言是一种用于在程序执行过程中进行调试的工具&#xff0c;能够帮助开发者验证程序的某些假设是否为真。如果断言失败&#xff0c;程序会终止&#xff0c;并输出一个错误消息&#xff0c;通常包含出错的文件名和行…

13【MySQL必知必会】分组数据(GROUP BY,HAVING)

SQL语句 /*第13章 分组数据关键词&#xff1a;分组数据&#xff0c;GROUP BY&#xff0c;HAVING*/-- 计算供应商ID为1003的产品数量 SELECT COUNT(*) AS num_prods FROM products WHERE vend_id 1003;-- 按供应商ID分组&#xff0c;统计每个供应商的产品数量 SELECT vend_id,…

Linux网络工具:跟踪 TCP 连接的命令tcptrack命令详解

目录 一、概述 二、 用法 1、基本用法 2、选项 三、安装 1、说明 2、Debian 系统中安装 3、centos中安装 &#xff08;1&#xff09;下载源代码 &#xff08;2&#xff09;编译源代码 &#xff08;3&#xff09;安装 四、示例和输出 1. 显示所有 TCP 连接 2. 只跟…

微信监控销售防飞单系统,让你的团队业绩稳如泰山!

团队中偶尔出现的私单、飞单问题而烦恼不已&#xff1f;你是否渴望拥有一个神器&#xff0c;能够实时监控销售过程&#xff0c;确保团队业绩的稳健增长&#xff1f;今天&#xff0c;就让我们一起探索这款神奇的“微信监控销售防飞单系统”&#xff0c;让你的销售团队如虎添翼&a…

React 渲染流程分析

React 页面是由组件组成的&#xff0c;从根组件直到叶组件&#xff0c;内部的组件数通过 Fiber 来保存并触发并发更新。页面的展示分为两部分&#xff0c;首先是初始化&#xff0c;所有组件首次展示&#xff0c;都要进行渲染&#xff0c;之后是更新流程&#xff0c;也就是页面产…

【利用python制作一个小程序生成爱心】

要利用Python制作一个小程序来生成爱心&#xff0c;我们可以使用字符图形或者利用图形库&#xff08;如turtle&#xff09;来绘制。下面我将分别展示这两种方法。 方法一&#xff1a;字符图形爱心 这种方法使用ASCII字符来模拟爱心的形状。 def print_love():heart [ ♥ …

实况:老菜鸟自力更生从零开始重学spring目标是画出一张唬人大图(二、源码下载编译)

前情提要&#xff1a;调试前的基础知识梳理 速览 “Spring”包含哪些东西源码下载源码编译1、编译工具选择&#xff1a;gradle2、使用gradle编译spring并导入idea预编译spring-oxm导入IDEA确认合适的jdk版本排除spring-aspects模块 开始调试 “Spring”包含哪些东西 可以明确的…

代码随想录算法训练营第二十四天| (回溯) 77. 组合、 216.组合总和III、17.电话号码的字母组合

77. 组合 题目链接&#xff1a;77. 组合 文档讲解&#xff1a;代码随想录 状态&#xff1a;很多细节忘了 思路&#xff1a;先画图&#xff0c;然后可以发现&#xff0c;从1到n中选择k个数&#xff0c;可以看成是一个递归过程&#xff0c;这个递归的深度就是k。然后遍历当前这层…

四舍五入 和 交换变量值 题目

题目 JAVA3 四舍五入分析&#xff1a;代码&#xff1a; JAVA4 交换变量值分析&#xff1a;代码&#xff1a;大佬代码&#xff1a; JAVA3 四舍五入 描述 定义一个int类型变量i,i为由浮点数变量d四舍五入后的整数类型&#xff0c;请将转换后的i进行输出。 输入描述&#xff1a;…

Centos7安装jdk8或11以及切换方案

目录 jdk安装 安装OpenJDK11 安装OpenJDK8 配置默认的 Java 版本 验证 全局环境变量&#xff08;选配&#xff09; 个人版&#xff08;自己可以用&#xff0c;公司不建议&#xff09; 公司版本 /etc/profile 和 ~/.bash_profile 区别 前言-与正文无关 生活远不止眼前的苦…

【动态规划】| 路径问题之不同路径 力扣62

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️ 专栏&#xff1a;动态规划 &#x1f397;️ 如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/unique-paths/description/ 通常动态规划的题目有…