C++11 左值引用和右值引用与引用折叠和完美转发
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 左值引用和右值引用与引用折叠和完美转发的更多相关文章
- c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用
为什么要用移动语义 先看看下面的代码 // rvalue_reference.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #includ ...
- C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward
这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运行测试过的,希望能用这些帮助理 ...
- c++11 左值引用、右值引用
c++11 左值引用.右值引用 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #i ...
- 左值与右值,左值引用与右值引用(C++11)
右值引用是解决语义支持提出的 这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运 ...
- C++11的左值引用与右值引用总结
概念 在C++11中,区别表达式是左值或右值可以做这样的总结:当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份(在内存中的位置).左值有持久的状态,而右值要 ...
- C++11左值引用和右值引用
转载:https://www.cnblogs.com/golaxy/p/9212897.html C++11的左值引用与右值引用总结 概念 1.&与&& 对于在C++中,大家 ...
- C++11常用特性介绍——左值引用、右值引用
一.左值.右值 1)左值:可以放在赋值号左侧.可以被赋值的值:左值必须要在内存中有实体. 2)右值:必须放在赋值号右侧.取出值赋值给其它变量:右值可以在内存中也可以在CPU寄存器中. 二.引用 引用是 ...
- 【C/C++开发】C++11:左值引用VS右值引用
左值引用VS右值引用 左值引用对于一般的C++程序员再熟悉不过,但对于右值引用(C++0X新特性),就稍微有点不知所云 左值VS右值 在定义变量的时候,经常会用到左值和右值,比如:int a = 1; ...
- C++的左值,右值,左值引用,右值引用
参考大神链接: https://blog.csdn.net/u012198575/article/details/83142419 1.左值与右值 https://msdn.microsoft.com ...
随机推荐
- ML Pipelines管道
ML Pipelines管道 In this section, we introduce the concept of ML Pipelines. ML Pipelines provide a uni ...
- 自动机器学习(AutoML)
自动机器学习(AutoML) 不再需要苦恼于学习各种机器学习的算法 目录: 一.为什么需要自动机器学习 二.超参数优化 Hyper-parameter Optimization 三.元学习 Meta ...
- Win10 下python_appium的Android手机自动化环境搭建
前提: 已经安装好了Java环境,且配置了环境变量 已经安装python3.8.2,已经安装pycham. 一.安装appium_client ,pycham中也需要安装 二.安装node.js(需要 ...
- Python-selenium,切换句柄及封装
一.获取当前句柄及所有句柄 handle=driver.current_window_handle #获取当前窗口句柄print(handle)handles=driver.window_handle ...
- ES6深拷贝与浅拷贝
今天小编和大家一起探讨js中深拷贝和浅拷贝,简单一点理解就是,对于引用数据类型,深拷贝是数据引用地址不同,在改变一个数据的时候,不会影响另一个数据.而浅拷贝刚好相反.两个数据引用的是同一个堆内存地址, ...
- DOS命令行(3)——Windows运行窗口打开特定功能
cmd 开启命令解释权或启用Windows中的某程序 cmd /c 执行完命令后关闭命令窗口 cmd /k 执行完命令后不关闭命令窗口 winver 查看Windows版本信息版权信息授权信息 ...
- 京东 Vue3 组件库支持小程序开发啦!
源码抢先看: https://github.com/jdf2e/nutui NutUI 3.0 官网:https://nutui.jd.com/3x/#/ 小程序多端适配 设计初衷 在跨端小程序的开发 ...
- Java知识复习(三)
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?用contains来区分是否有重复的对象.还是都不用. 在比较时先调用hashCode方法, ...
- string转char*/char[]
转char* 主要有三种方法可以将str转换为char*类型,分别是:data(); c_str(); copy(); 1.data() data()仅返回字符串内容,而不含有结束符'\0' std: ...
- 19、lnmp_mysql、nfs组件分离
19.1.LNMP一体机的数据库分离成独立的数据库: 1.根据以上学习过的方法在db01服务器上安装独立的mysql数据库软件: 2.在web01服务器上导出原先的数据库: [root@web01 t ...