转载:https://www.cnblogs.com/golaxy/p/9212897.html

C++11的左值引用与右值引用总结

概念

1、&与&&
  对于在C++中,大家对于符号“ & ”的第一映像是引用和取地址,对符号“ && ”的第一映像是逻辑与。但是在C++11中我们会看到下方这种表示方法:

int &&k=i+k;
1.1
  对于第一眼见到上述的表达方式时,估计会一脸懵逼。下面对此做一个简述。
  引用 & 是一个类型变量的别名。
  通常使用 “ & ”是作为普通的左值引用,左值是可以放在赋值号 “ = ”的左边的值。
  &&是右值引用,右值是只能放在 “ = ” 右边的值,右值没有一个 “ 变量 ”名字。如:

int && k =i+j;
1.2
  i+j 返回的值可以视做是放在一个临时存放内存空间里的,这个空间并不能用来赋值,你不能些i+j=5等; && 可以把这种临时的值和存在变量里的值区分开来。
  右值短暂,右值只能绑定到临时对象。所引用的对象将要销毁或对象没有其他用户。
  初始化时右值引用一定要用一个右值表达式绑定,初始化之后,可以用左值表达式或修改右值引用的所引用临时对象的值。
  右值引用是对临时对象的一种引用,它是在初始化时完成引用的,但是右值引用不代表引用临时对象后,就不能改变右值引用所引用对象的值。仍然可以在初始化后改变临时对象的值。

  对于引用类型,可以用于它所引用对象类型的可以用的地方(把他当成普通变量),只不过用到的值是它所引用的对象的值,还可以用于移动构造和赋值函数的地方

在C++11中,区别表达式是左值或右值可以做这样的总结:当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。左值有持久的状态,而右值要么是字面常量,要么是在表达式求值过程中创建的对象,即左值持久,右值短暂

以上的定义来自于C++Primer(5th)第121页和第471页。可能令人困惑,看了接下来的例子就明白了

[cpp] view plain copy

 
  1. int &&rr1 = 42;//正确,字面常量是右值
  2. int &&rr2 = rr1;//错误,表达式rr1是左值

特性中的应用

decltype关键字

使用关键字decltype的时候,左值和右值有所不同。如果表达式的求值结果是左值,decltype作用于该表达式(不是变量)得到一个引用类型,例如,假定p的类型是int*,因为解引用运算符生成左值,所以decltype(*p)的结果是int&。另一方面,因为取地址运算符生成右值,所以decltype(&p)的结果是int**,也就是说,结果是一个指向整型指针的指针。

lambda表达式

lambda表达式是形如auto f = [ ]{ }的函数。

lambda可指定其捕获列表的类型,[&]表示捕获列表采用隐式引用捕获方式lambda函数体中所使用的来自所在函数的实体都采用引用方式使用,[=]表示采用值捕获方式。

[cpp] view plain copy

 
  1. /*f1的sz是隐式值捕获,f2的sz是隐式引用捕获
  2. auto f1 = [=](const string &s)
  3. { return s.size() >=sz; }
  4. auto f2 = [&](const string &s)
  5. { return s.size() >=sz; }

拷贝控制

移动构造函数使用右值引用的形参

[cpp] view plain copy

 
  1. class Foo
  2. {
  3. //移动构造函数
  4. Foo(Foo&&);
  5. };

引用折叠和实参推断

    实参推断,按照实参和形参匹配的规则。
    引用折叠:
           通常情况下,我们不能将一个右值引用绑定到一个左值上,但是C++语言在正常绑定规则外定义了两个例外规则,允许这种绑定。

第一个例外规则影响右值引用的参数推断如何进行:当我们将一个左值传递给函数的右值引用参数,且此右值引用指向模板类型参数(如T&&),编译器推断模板类型参数为实参的左值引用类型。

[cpp] view plain copy

 
  1. //编译器推断T类型是int&(左值引用),而非int
  2. template <typename T> void f(T&&);
  3. int i = 0;
  4. f(i);

引用折叠:在所有情况下(除了一个例外),引用会折叠成一个普通的左值引用类型。

[html] view plain copy

 
  1. 即:对于一个给定类型X
  2. <ol>
  3. <li>X& & ,X& && ,X&& &都折叠成类型X&<li>
  4. <li>类型X&& &&折叠成X&&<li>
  5. </ol>

注:引用折叠只能应用于间接创建的引用的引用,如类型别名或模板参数。

这两个规则导致了两个重要结果:

如果一个函数参数是一个指向模板类型参数的右值引用(如T&&),则他可以被绑定到一个左值。且

如果实参是一个左值,则推断出的模板实参类型将是一个左值引用,且函数参数将被实例化为一个普通的左值引用参数(T&)

也暗示了:我们可以将任意类型的实参传递给T&&类型的函数参数。

函数重载

    重载函数定义两个版本,一个版本接受一个指向const的左值引用,第二个版本接受一个指定非const的右值引用。即可接受所有可转换成当前类型的对象
[cpp] view plain copy

 
  1. void Foo(const X&);
  2. void Foo(X&&);

我们知道,非常量可以初始化一个底层const,反过来却不行,所以第一种版本可以接收任何能转换成类型X的任何对象。第二种版本只可以传递非const右值,由于精确匹配规则,传递非const右值时,会调用第二种版本,尽管第一种版本也可以接受。

一般来说,我们不需要为函数操作定义接受一个const X&&或是一个普通的X&参数的版本。当我们希望从实参“窃取‘数据时,通常传递一个右值引用。为了达到这一目的,实参不能使const的。类似的,从一个对象进行拷贝的操作,不应该改变该对象,因此,通常不需要定义一个接受一个普通的X&参数的版本。

C++11左值引用和右值引用的更多相关文章

  1. c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用

    为什么要用移动语义 先看看下面的代码 // rvalue_reference.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #includ ...

  2. C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward

    这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运行测试过的,希望能用这些帮助理 ...

  3. c++11 左值引用、右值引用

    c++11 左值引用.右值引用 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #i ...

  4. 左值与右值,左值引用与右值引用(C++11)

    右值引用是解决语义支持提出的 这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运 ...

  5. C++11的左值引用与右值引用总结

    概念 在C++11中,区别表达式是左值或右值可以做这样的总结:当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份(在内存中的位置).左值有持久的状态,而右值要 ...

  6. C++11常用特性介绍——左值引用、右值引用

    一.左值.右值 1)左值:可以放在赋值号左侧.可以被赋值的值:左值必须要在内存中有实体. 2)右值:必须放在赋值号右侧.取出值赋值给其它变量:右值可以在内存中也可以在CPU寄存器中. 二.引用 引用是 ...

  7. C++11 左值引用和右值引用与引用折叠和完美转发

    1.左值与右值 最感性的认识. 当然,左值也是可以在右边的. 左值是可以被修改的,右值不能. 当然取地址也是. 生存周期一般左值会比右值的长,一般右值都计算时产生的无名临时对象,存在时间比较短. 下面 ...

  8. 【C/C++开发】C++11:左值引用VS右值引用

    左值引用VS右值引用 左值引用对于一般的C++程序员再熟悉不过,但对于右值引用(C++0X新特性),就稍微有点不知所云 左值VS右值 在定义变量的时候,经常会用到左值和右值,比如:int a = 1; ...

  9. C++的左值,右值,左值引用,右值引用

    参考大神链接: https://blog.csdn.net/u012198575/article/details/83142419 1.左值与右值 https://msdn.microsoft.com ...

随机推荐

  1. bundle install 老是中断,可以在gemfile里面把source换成taobao源,可以自动安装

    bundle install 老是中断,可以在gemfile里面把source换成taobao源,可以自动安装

  2. tornado异步编程

    说明 以下的例子都有2个url,一个是耗时的请求,一个是可以立刻返回的请求,,我们希望的是访问立刻返回结果的请求不会被其他耗时请求影响 非异步处理 现在我们请求sleep然后同时请求justnow,发 ...

  3. Linux 如何杀死僵尸进程

    问题描述: shell > top top - :: up days, :, user, load average: 0.23, 0.81, 1.07 Tasks: total, running ...

  4. 【302】C# TreeView 控件使用说明

    参考:C# 中treeview 树节点图标的动态加载,及选中时图标改变 参考:C# TreeView 控件的综合使用方法 参考:TreeView 类 参考:TreeNode 类 1. 添加根和子级 通 ...

  5. 【原】Coursera—Andrew Ng机器学习—编程作业 Programming Exercise 4—反向传播神经网络

    课程笔记 Coursera—Andrew Ng机器学习—课程笔记 Lecture 9_Neural Networks learning 作业说明 Exercise 4,Week 5,实现反向传播 ba ...

  6. 【ZOJ 3228】Searching the String 【AC自动机】

    题意 给出n个模式串和一个文本串,输出各个模式串在文本串中出现的次数.模式串有两种类型,0类型代表可以有重叠,1类型代表不能有重叠.模式串可能出现重复. 分析 算是AC自动机的模板题? 因为模式串可以 ...

  7. 高性能Web服务器Nginx的配置与部署研究(12)应用模块之Memcached做文件缓存时压缩引起的问题

    在上一篇文章中,提到的Nginx的Memcached模块应用场景,主要是作为文件缓存.然后就发现了一个问题,当以字节数组方式缓存较大的文件时,缓存数据会被压缩,从而在读取的时候出现问题. (本文欢迎转 ...

  8. photoshop最全快捷键列表

    一.工具箱(多种工具共用一个快捷键的可同时按[Shift]加此快捷键选取) 矩形.椭圆选框工具 [M] 移动工具 [V] 套索.多边形套索.磁性套索 [L] 魔棒工具 [W] 裁剪工具 [C] 切片工 ...

  9. python爬虫之Scrapy 使用代理配置——乾颐堂

    在爬取网站内容的时候,最常遇到的问题是:网站对IP有限制,会有防抓取功能,最好的办法就是IP轮换抓取(加代理) 下面来说一下Scrapy如何配置代理,进行抓取 1.在Scrapy工程下新建“middl ...

  10. [SoapUI] 通过SoapUI发送POST请求,请求的body是JSON格式的数据

    通过SoapUI发送POST请求,请求的body是JSON格式的数据: data={"currentDate":"2015-06-19","reset ...