1.左值与右值

最感性的认识。

当然,左值也是可以在右边的。

左值是可以被修改的,右值不能。

当然取地址也是。

生存周期一般左值会比右值的长,一般右值都计算时产生的无名临时对象,存在时间比较短。

下面还有一种情况也要区分。

2.左值引用和右值引用

左值引用:可以引用一个对象,有时候也可以绑定一个右值。

右值引用:只能引用右值。

1左值引用示例

看以下代码,比较正常。

	int a = 3;
int &p1 = a; // 左值引用

若左值引用右值将报错

但加上const就可以引用了

2右值引用示例

不能把左值绑定到右值,但使用move可以把左值转换右值就可以绑定

示例1

示例2

示例3

理解了上边知识,接下来是引用折叠规则,

3.引用折叠

先看演示代码

#include <iostream>
using namespace std; using lRef = int&; //左值引用
using rRef = int&&; //右值引用 int main(int argc, char **argv)
{
is_lvalue_reference<lRef &>::value ?
cout << "lRef & 左值引用" << endl :
cout << "lRef & 右值引用" << endl; is_lvalue_reference<lRef &&>::value ?
cout << "lRef && 左值引用" << endl :
cout << "lRef && 右值引用" << endl; is_rvalue_reference<rRef &>::value ?
cout << "rRef & 右值引用" << endl :
cout << "rRef & 左值引用" << endl; is_rvalue_reference<rRef &&>::value ?
cout << "rRef && 右值引用" << endl :
cout << "rRef && 左值引用" << endl; return 0;
}

调试结果

这就是引用折叠规则。

这怎么理解呢,看下图

可以看到只有都是右值引用的时候才是右值引用,当然只有一个右值引用的情况下自然而然也是右值引用。

这是就引用折叠。

4.完美转发

主要用于参数转发时是左值传入还是右转入

考虑以下代码

#include <iostream>
using namespace std; template<typename T>
void Fun1(T& v)
{
cout << "左值引用调用" << v << endl;
} template<typename T>
void Fun1(T&& v)
{
cout << "右值引用调用" << v <<endl;
} template<typename T>
void Fun(T&& v)
{
Fun1(v);
} int main(int argc, char **argv)
{
int a = 3; Fun(a); return 0;
}

主函数里给Fun传入a,根据上边知识,a是一个左值,看调试结果是调用哪一个重载版本Fun1

结果跟预想的一样,接下来更改换右值传入。

int main(int argc, char **argv)
{ Fun(5); return 0;
}

调试结果

我们发现跟想象中不一样!!!

这时候该怎么办。

c++11中提供了一个用于完美转发的函数forward。

还提供了一个move函数,用于把左值变成右值的方法。

forward会根据引用折叠规则得出传入的是左值引用还是右值引用

接下来只需更改一下Fun函数,其他的不变

template<typename T>
void Fun(T&& v)
{
Fun1(forward<T>(v));
}

调试结果

发现跟我们预想一样了。

完美转发完整示例

#include <iostream>
using namespace std; template<typename T>
void Fun1(T& v)
{
cout << "左值引用调用" << v << endl;
} template<typename T>
void Fun1(T&& v)
{
cout << "右值引用调用" << v <<endl;
} template<typename T>
void Fun(T&& v)
{
Fun1(forward<T>(v));
} int main(int argc, char **argv)
{
int a = 1;
Fun(a);
Fun(move(a)); const int b = 2;
Fun(b);
Fun(move(b)); Fun(5); return 0;
}

调试结果

5.结语

学无止境。

---End

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左值引用和右值引用

    转载:https://www.cnblogs.com/golaxy/p/9212897.html C++11的左值引用与右值引用总结 概念 1.&与&&  对于在C++中,大家 ...

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

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

  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. 旷视MegEngine网络搭建

    旷视MegEngine网络搭建 在 基本概念 中,介绍了计算图.张量和算子,神经网络可以看成一个计算图.在 MegEngine 中,按照计算图的拓扑结构,将张量和算子连接起来,即可完成对网络的搭建.M ...

  2. CodeGen字段循环Field Loop

    CodeGen字段循环Field Loop 字段循环是一个模板文件构造,它允许迭代CodeGen拥有的有关字段的集合.这些字段定义可以来自以下两个位置之一: •如果基于从存储库结构中获取的信息生成代码 ...

  3. 通过Mellanox ConnectX NIC使用XDP加速

    通过Mellanox ConnectX NIC使用XDP加速 Accelerating with XDP over Mellanox ConnectX NICs XDP(eXpress Data Pa ...

  4. NSight Compute 用户手册(上)

    NSight Compute 用户手册(上) 非交互式配置文件活动 从NVIDIA Nsight Compute启动目标应用程序 启动NVIDIA Nsight Compute时,将出现欢迎页面.单击 ...

  5. OSPF-OSPF通用报头

    验证理论 1.OSPF信息类型,每个信息类型的作用,每个信息类型中每个字段存在的价值 第一节--通用报头 实验拓扑: 初始配置: 将接口配置地址,抓包开始后配置上OSPF 1.OSPF通用报头 OSP ...

  6. Excel创建序列号1000个

    一.输入1,并且选择 二.开始-填充 三.选择序列 四.选择列-等差序列-步张值输入1 终止值输入1000 点击确定 五.查看结果,选中这一列 六.快捷键 Ctrl+下键 则跳转到最下方,上键则是最上 ...

  7. 安全Web服务器

    https协议: 443 端口 虚拟Server0: 1.部署 网站证书(营业执照)# cd /etc/pki/tls/certs/ # wget http://classroom.example.c ...

  8. NX二次开发-克隆操作

    模板文件: 克隆替换字符串: 1 #include "Text.h" 2 extern DllExport void ufsta(char *param, int *returnC ...

  9. java并发编程JUC第十一篇:如何在线程之间进行对等数据交换

    java.util.concurrent.Exchanger可以用来进行数据交换,或者被称为"数据交换器".两个线程可以使用Exchanger交换数据,下图用来说明Exchange ...

  10. Spring学习日记02_IOC_属性注入_其他类型属性

    ICO操作Bean管理(xml注入其它类型属性) 字面量 null值 <property name="address"> <null></null&g ...