EasyC++ 右值引用
目录
- 1.左值和右值
- 2.左值引用和右值引用
文章转自:公众号:Coder梁(ID:Coder_LT)
1.左值和右值
在我们之前的文章当中,介绍的都是左值引用。C++11在左值引用的基础上推出了右值引用,由于是新特性,加上使用的频率也不是很高,有一定的学习成本。
我们先把引用这个概念抛开,先来看看什么是左值什么是右值。其实很简单,左值可以取地址,位于等于号的左侧。而右值没办法取地址,位于等于号的右侧。
int a = 4;
比如我们定义了一个int型的变量a,让它的值等于4。其中a位于等于号的左侧,并且我们可以求a的地址。而4位于等于号的右侧,我们没有办法对4取地址。所以a是左值,4是右值。
再比如:
int test() {
return 4;
}
int a = test();
同样,a位于等于号的左侧,有办法取地址是个左值。而test()是一个临时值没办法取地址,是个右值。
所以到这里就比较清楚了,有地址的变量就是左值,没有地址的常量值、临时变量就是右值。
2.左值引用和右值引用
明白了左值、右值的概念再来看看左值引用、右值引用就简单了。左值引用顾名思义就是能够指向左值不能指向右值的引用。
int a = 4; int &b = a; // 合法 int &c = 4; // 非法
但是左值引用也有例外,就是使用const修饰的左值引用是可以指向右值的:
const int &b = 4;
因为const修饰的引用无法再更改,所以可以指向右值。如果大家度过STL代码的话,会发现其中一些函数的入参是const &目的就是为了能够兼容传参是常量的情况。比如vector当中的push_back:
void push_back (const value_type& val);
右值引用和左值引用的概念类似,也就是能够指向右值但不能指向左值的引用。为了和左值引用区别, 使用&&也就是两个&符。老实讲这个符号很令人费解,因为它和and的含义相同。
int a = 4; int &&b = 4; // 合法 int &&c = a; // 非法
上面第三行代码非法的原因是c是一个右值引用,它不能指向左值。如果我们非要指向呢?也不是没有办法,可以使用std::move函数,它可以将一个左值转换成右值。
using namespace std; int a = 4; int &&c = move(a);
move函数听起来似乎是移动的意思,但其实它并没有移动变量,只不过做了一个类似于类型转换的操作。
不知道大家看到这里有没有觉得头大,其实还没有结束,还有一点很重要。即左值引用和右值引用这两者本身都是左值引用:
void test(int && tmp) {
tmp = 2333;
}
using namespace std;
int a = 4;
int &b = a;
int &&c = 4;
test(a); // 非法
test(b); // 非法
test(c); // 非法
test(move(a));// 合法
test(move(b));// 合法
test(move(c));// 合法
C++中的引用是一个非常大的范畴,除了左值引用、右值引用之外还有非常多的细节。比如万能引用、引用折叠、完美转发等……
到此这篇关于C++ 右值引用的文章就介绍到这了,更多相关右值引用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
相关推荐
-
C++模板重载
目录 1.重载模板 2.问题 文章转自 公众号:Coder梁(ID:Coder_LT) 1.重载模板 函数模板可以使得同一个函数对不同类型使用,非常地方便.但有的时候类型不同,只是通过模板是没办法解决的, 可能逻辑上也会有所区别,这个时候只是使用模板是无法解决的. 为了满足这种需求,我们可以像是重载函数那样重载模板.和常规的函数一样,重载的模板的函数特征,也就是入参的数量和类型必须有所不同. 举个例子:比如我们之前定义了一个函数模板用来交换两个变量的值.如果我们要交换的不只是变量,而是两个数组
-
详解C++中的自动存储
C++有3种管理数据内存的方式即自动存储(栈存储).静态存储和动态存储(堆存储).在不同的方式下,内存的分配形式和存在时间的长短都不同. 下面对自动存储进行说明. 自动存储(栈存储) 对于函数的形参.内部声明的变量及结构变量等,编译器将在函数执行时为形参自动分配存储空间,在执行到变量和结构变量等的声明语句时为其自动分配存储空间,因此称其为自动变量(Automatic Variable),有的教科书也称其为局部变量,在函数执行完毕返回时,这些变量将被撤销,对应的内存空间将被释放. 事实上,自动变量
-
C++模板显式具体化
出品 | 公众号:Coder梁(ID:Coder_LT) 前文当中说了,模板函数虽然非常好用,但是也存在一些问题.比如有的操作并不是对所有类型都适用的,针对这种情况C++提供了一个解决方案,就是针对特定类型提供具体化的模板定义.这里的具体可以理解成类型的具体. 我们来看一个C++ Primer当中的例子,假设现在我们有一个结构体叫做job: struct job { string name; double salary; int floor; } 对于结构体是可以整体赋值的,所以之前的Swap函
-
C++编写头文件
文章转自公众号:Coder梁(ID:Coder_LT) 我们之前做的左右示例都是在一个单独的cpp文件当中完成的,当我们要做一个相对复杂或大型的项目时,我们显然不能把所有代码都写在一个cpp里.这就需要我们拆分代码,但代码按照逻辑划分,写入不同的cpp文件当中. 在我们编译的时候,我们可以将这些cpp文件分别单独编译,最后再连接到一起.这样做的好处是,当我们只修改了某一个文件的时候,可以只用单独编译那一个文件,不会影响其他文件的编译结果.一般来说大型项目,都会使用一下自动化的编译工具,比如mak
-
EasyC++单独编译
文章转自:微信公众号:Coder梁(ID:Coder_LT) 联合编译: 在上一篇当中,我们编写好了头文件coordin.h,现在我们要完成它的实现 头文件当中只能放一些生命和常量的定义,不能有具体的实现.所以我们要把具体的实现单独放入一个cpp文件当中.因为我们的头文件叫做coordin.h,那么我们与之对应的cpp文件自然就叫做coordin.cpp. 在coordin.h当中我们声明了两个函数,自然我们就要完成这两个函数的实现: #include <cstdio> #include &l
-
C++函数模板介绍
文章转自: 公众号:Coder梁(ID:Coder_LT) 函数模板: 所谓函数的模板,本质上也就是使用泛型来定义函数. 所谓的泛型其实也就是不定的类型,比如说我们使用vector的时候,可以定义各种类型的vector,可以定义存储int型的vector也可以定义存储float类型的,也可以定义存储其他类型.我们在声明的时候将存储的类型当做参数传给了模板. 泛型可以用具体的类型,比如(int或double)替换,通过将类型作为参数传给模板,编译器会根据传递的参数类型生成该类型的函数.这种方式也被
-
EasyC++自动存储持续性
转自微信公众号:Coder梁(ID:Coder_LT) 自动存储持续性: 这个概念乍一看有些拗口,其实它很简单,指的是在函数定义中声明的变量的存储持续性是自动的:它们在程序开始执行其所属的函数或代码块时被创建,在执行完函数或代码块时,它们使用的内存被释放. 在默认情况下,我们在函数中声明的变量和函数的参数都是自动存储持续性,它的作用于为局部,没有链接性. 这里的链接性描述了名称如何在不同的单元之间共享,链接性为外部的名称可以在文件之间共享,链接性为内部的名称只能由一个车文件中的函数共享.自动变量
-
EasyC++ 右值引用
目录 1.左值和右值 2.左值引用和右值引用 文章转自:公众号:Coder梁(ID:Coder_LT) 1.左值和右值 在我们之前的文章当中,介绍的都是左值引用.C++11在左值引用的基础上推出了右值引用,由于是新特性,加上使用的频率也不是很高,有一定的学习成本. 我们先把引用这个概念抛开,先来看看什么是左值什么是右值.其实很简单,左值可以取地址,位于等于号的左侧.而右值没办法取地址,位于等于号的右侧. int a = 4; 比如我们定义了一个int型的变量a,让它的值等于4.其中a位于等于号的
-
详解C++11中的右值引用与移动语义
C++11的一个最主要的特性就是可以移动而非拷贝对象的能力.很多情况都会发生对象的拷贝,有时对象拷贝后就立即销毁,在这些情况下,移动而非拷贝对象会大幅度提升性能. 右值与右值引用 为了支持移动操作,新标准引入了一种新的引用类型--右值引用,就是必须绑定到右值的引用.我们通过&&而不是&来获得右值引用.右值引用一个重要的特性就是只能绑定到将要销毁的对象. 左值和右值是表达式的属性,一些表达式生成或要求左值,而另一些则生成或要求右值.一般而言,一个左值表达式表示的是一个对象的身份,而右
-
浅析C++11中的右值引用、转移语义和完美转发
1. 左值与右值: C++对于左值和右值没有标准定义,但是有一个被广泛认同的说法:可以取地址的,有名字的,非临时的就是左值;不能取地址的,没有名字的,临时的就是右值. 可见立即数,函数返回的值等都是右值;而非匿名对象(包括变量),函数返回的引用,const对象等都是左值. 从本质上理解,创建和销毁由编译器幕后控制的,程序员只能确保在本行代码有效的,就是右值(包括立即数);而用户创建的,通过作用域规则可知其生存期的,就是左值(包括函数返回的局部变量的引用以及const对象),例如: int& fo
-
C++标准之(ravalue reference) 右值引用介绍
1.右值引用引入的背景 临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题.但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了CopyElision.RVO(包括NRVO)等编译器优化技术,它们可以防止某些情况下临时对象产生和拷贝.下面简单地介绍一下CopyElision.RVO,对此不感兴趣的可以直接跳过: (1)CopyElision CopyElision技术是为了防止某些不必要的临时对象产生和拷贝,例如: 复制代码 代码如下: structA{ A(
-
深入解读C++中的右值引用
右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一,这点从该特性的提案在C++ - State of the Evolution列表上高居榜首也可以看得出来. 从实践角度讲,它能够完美解决C++中长久以来为人所诟病的临时对象效率问题.从语言本身讲,它健全了C++中的引用类型在左值右值方面的缺陷.从库设计者的角度讲,它给库设计者又带来了一把利器.从库使用者的角度讲,不动一兵一卒便可以获得"免费的"效率提升- 在标准C++语言中,临时量(术语为右值,因其出
-
浅谈C++左值引用和右值引用
实例如下: #include<iostream> #include<utility> #include<vector> using namespace std; int f(); int main() { vector<int>vi(100); int i=42; int &&r1=i;//error不能把右值引用绑到左值上 int &&r2=10; int &r3=i; int &r4=10;//error非
-
C++11右值引用和std::move语句实例解析(推荐)
右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一.从实践角度讲,它能够完美解决C++中长久以来为人所诟病的临时对象效率问题.从语言本身讲,它健全了C++中的引用类型在左值右值方面的缺陷.从库设计者的角度讲,它给库设计者又带来了一把利器.从库使用者的角度讲,不动一兵一卒便可以获得"免费的"效率提升- 下面用实例来深入探讨右值引用. 1.什么是左值,什么是右值,简单说左值可以赋值,右值不可以赋值.以下面代码为例,"A a = getA();&q
-
C++11右值引用和转发型引用教程详解
右值引用 为了解决移动语义及完美转发问题,C++11标准引入了右值引用(rvalue reference)这一重要的新概念.右值引用采用T&&这一语法形式,比传统的引用T&(如今被称作左值引用 lvalue reference)多一个&. 如果把经由T&&这一语法形式所产生的引用类型都叫做右值引用,那么这种广义的右值引用又可分为以下三种类型: 无名右值引用 具名右值引用 转发型引用 无名右值引用和具名右值引用的引入主要是为了解决移动语义问题. 转发型引用的引
-
C++11的右值引用的具体使用
C++11 引入了 std::move 语义.右值引用.移动构造和完美转发这些特性.由于这部分篇幅比较长,分为3篇来进行阐述. 在了解这些特性之前,我们先来引入一些问题. 一.问题导入 函数返回值是传值的时候发生几次对象构造.几次拷贝? 函数的形参是值传递的时候发生几次对象构造? 让我们先来看一段代码, // main.cpp #include <iostream> using namespace std; class A{ public: A(){ cout<<"cla
-
C++ lambda 捕获模式与右值引用的使用
lambda 表达式和右值引用是 C++11 的两个非常有用的特性. lambda 表达式实际上会由编译器创建一个 std::function 对象,以值的方式捕获的变量则会由编译器复制一份,在 std::function 对象中创建一个对应的类型相同的 const 成员变量,如下面的这段代码: int main(){ std::string str = "test"; printf("String address %p in main, str %s\n", &a
随机推荐
- php中将数组存到文件里的实现代码
- Python实现栈的方法
- VBS教程:属性-VolumeName 属性
- Java数据导入功能之读取Excel文件实例
- ios仿侧边抽屉效果实现代码
- php 批量生成html,txt文件的实现代码
- python实现自动登录人人网并采集信息的方法
- 枚举窗口句柄后关闭所有窗口示例
- 用CSS给图片打标的方法
- IP地址输入框
- jQuery中live方法的重复绑定说明
- SQL事务用法begin tran,commit tran和rollback tran的用法
- jquery实现图片列表鼠标移入微动
- JS中将多个逗号替换为一个逗号的实现代码
- 探秘C# 6.0 的新特性
- mantis安装、配置和使用中的问题小结
- C++实现顺序排序算法简单示例代码
- 防火墙专题
- 详解Python中的正斜杠与反斜杠
- 详解@angular/cli 改变默认启动端口两种方式
