c++ 11 新特性之 左值右值
左值:可以取地址并且有名字的东西就是左值。或者可以放到等号左边的东西叫左值。
右值:不能取地址的没有名字的东西就是右值。或者不可以放到等号左边的东西就叫右值。
纯右值:运算表达式产生的临时变量、不和对象关联的原始字面量、非引用返回的函数返回临时变量、lambda表达式等都是纯右值。
将亡值:可以理解为即将要销毁的值。
左值引用:对左值进行引用的类型。
右值引用:对右值进行引用的类型。
移动语义:转移资源所有权,类似于转让或者资源窃取的意思,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用。
完美转发:可以写一个接受任意实参的函数模板,并转发到其它函数,目标函数会收到与转发函数完全相同的实参。
返回值优化:当函数需要返回一个对象实例时候,就会创建一个临时对象并通过复制构造函数将目标对象复制到临时对象,这里有复制构造函数和析构函数会被多余的调用到,有代价,而通过返回值优化,C++标准允许省略调用这些复制构造函数
左值一般有:
函数名和变量名
返回左值引用的函数调用
前置自增自减表达式++i、--i
由赋值表达式或赋值运算符连接的表达式(a=b, a += b等)
解引用表达式*p
字符串字面值"abcd"
纯右值、将亡值
纯右值和将亡值都属于右值。
纯右值
运算表达式产生的临时变量、不和对象关联的原始字面量、非引用返回的函数返回临时变量、lambda表达式等都是纯右值。
举例:
除字符串字面值外的字面值
返回非引用类型的函数调用
后置自增自减表达式i++、i--
算术表达式(a+b, a*b, a&&b, a==b等)
取地址表达式等(&a)
将亡值
将亡值是指C++11新增的和右值引用相关的表达式,通常指将要被移动的对象、T&&函数的返回值、std::move函数的返回值、转换为T&&类型转换函数的返回值,将亡值可以理解为即将要销毁的值,通过“盗取”其它变量内存空间方式获取的值,在确保其它变量不再被使用或者即将被销毁时,可以避免内存空间的释放和分配,延长变量值的生命周期,常用来完成移动构造或者移动赋值的特殊任务。
A a;
auto c = std::move(a);
auto d = static_cast<A&&>(a);
左值引用、右值引用
左值引用就是对左值进行引用的类型,右值引用就是对右值进行引用的类型,他们都是引用,都是对象的一个别名,并不拥有所绑定对象的堆存,所以都必须立即初始化。
type &name = exp; // 左值引用
type &&name = exp; // 右值引用
左值引用:
等号右边的值必须可以取地址,如果不能取地址,则会编译失败;
或者可以使用const引用形式,但这样就只能通过引用来读取输出,不能修改数组,因为是常量引用。
如:
int &a = 1; //不行
int &b = funct(); //不行
const int &c = funct();
右值引用:
通常情况下,右值引用是不能绑定到任何的左值的。
右值不存在名称,只能通过引用找到它的存在。
如: int && a = funct();
那表达式等号右边的值需要时右值,可以使用std::move函数强制把左值转换为右值。
int a = 4;
int &&b = a; // error, a是左值 int &&c = std::move(a); // 可以
右值存在的最大价值就是移动语义,另外一个价值是用于转发 左值引用的版本是一个拷贝构造版本,右值引用版本是一个移动构造版本。 编译器会隐式生成一个移动构造函数。如果声明了自定义的拷贝构造函数、拷贝赋值函数、析构函数中的一个或多个,编译器就不会生成默认版本。
拷贝构造/赋值 和移动构造/赋值函数必须同时提供,或者同时不提供。才能保证类同时具备拷贝和移动语义。只声明其中一种的话,类仅能实现一种语义。
具体的拷贝构造和移动构造函数见:
c++ 类与默认函数、包括构造函数和析构函数的特点_小飞侠hello的博客-CSDN博客
移动语义
可以理解为转移所有权,之前的拷贝是对于别人的资源,自己重新分配一块内存存储复制过来的资源,而对于移动语义,类似于转让或者资源窃取的意思,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用。
std::move 基本等同于一个类型转换 static_cast<T&&> (lvalue);而static_cast<T&&> (lvalue)调用移动构造函数。std::move既可以传递一个左值,也可以传递一个右值。
template<class _Ty>_NODISCARD constexpr remove_reference_t<_Ty>&&move(_Ty&& _Arg) noexcept{ // forward _Arg as movablereturn (static_cast<remove_reference_t<_Ty>&&>(_Arg));}
移动语义一定是要修改临时变量的值。
std::vector<string> vecs;vecs.push_back("1");vecs.push_back("2");std::vector<string> vecm = std::move(vecs); // 免去很多拷贝结果是 vecs 的大小为0
怎么利用移动语义呢,是通过移动构造函数
A(A&& a) {
this->data_ = a.data_;
a.data_ = nullptr;
cout << "move " << endl;
}
~A() {
if (data_ != nullptr) {
delete[] data_;
}
}
从拷贝、移动延伸到智能指针这类资源型的类型。
完美转发
完美转发指可以写一个接受任意实参的函数模板,并转发到其它函数,目标函数会收到与转发函数完全相同的实参,转发函数实参是左值那目标函数实参也是左值,转发函数实参是右值那目标函数实参也是右值。那如何实现完美转发呢,答案是使用std::forward()。
也是基于static_cast<T&&> (lvalue);的原理。forward和move差别并不大。
其使用场景包括:make_pair、 make_unique
背景:
规则1(引用折叠规则):如果间接的创建一个引用的引用,则这些引用就会“折叠”。在所有情况下(除了一个例外),引用折叠成一个普通的左值引用类型。一种特殊情况下,引用会折叠成右值引用,即右值引用的右值引用, T&& &&。即
- X& &、X& &&、X&& &都折叠成X&
- X&& &&折叠为X&&
规则2(右值引用的特殊类型推断规则):当将一个左值传递给一个参数是右值引用的函数,且此右值引用指向模板类型参数(T&&)时,编译器推断模板参数类型为实参的左值引用,如
template<typename T>
void f(T&&);int i = 42;
f(i)
上述的模板参数类型T将推断为int&类型,而非int。
从上述两个规则可以得出结论:如果一个函数形参是一个指向模板类型的右值引用,则该参数可以被绑定到一个左值上,
规则3:虽然不能隐式的将一个左值转换为右值引用,但是可以通过static_cast显示地将一个左值转换为一个右值。【C++11中为static_cast新增的转换功能】。
返回值优化(RVO)
是一种C++编译优化技术,当函数需要返回一个对象实例时候,就会创建一个临时对象并通过复制构造函数将目标对象复制到临时对象,这里有复制构造函数和析构函数会被多余的调用到,有代价,而通过返回值优化,C++标准允许省略调用这些复制构造函数。
根据effective modern c++中介绍,编译器进行RVO条件有二
- return 的值类型与 函数签名的返回值类型相同
- return的是一个局部对象
std::vector<int> return_vector(void) {
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> rval_ref = return_vector();
c++ 11 新特性之 左值右值相关推荐
- C++11新特性——移动语义,右值引用
移动语义 有一些类的资源是__不可共享__的,这种类型的对象可以被移动但不能被拷贝,如:IO 或 unique_ptr 库容器.string 和 shared_ptr 支持拷贝和移动,IO 和 uni ...
- C++11新特性(一)右值引用
@ 一.C++11简介 在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称.不过由于TC1主要是对C+ ...
- C++新特性探究(十三):右值引用(r-value ref)探究
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++11新特性之左值右值及移动语句与完美转发
C左值右值 左值和右值的由来 什么是左值和右值 左值右值的本质 引用 左值引用 右值引用 移动语句与完美转发 移动语句 实现移动构造函数和转移赋值函数 stdmove 完美转发Perfect Forw ...
- C++ C++11新特性--右值引用
左值与右值 在C语言中,左值和右值一般有两种区分的方法.可以出现在赋值符号"="的两边的值为左值,只能出现在赋值符号"="的右边的值为右值:还有一种说法是能取地 ...
- [C++11新特性](24)列表初始化,右值引用,可变参数模板,lambda表达式,包装器
文章目录 列表初始化 {}初始化 initializer_list auto.nullptr.范围for decltype STL的变化 右值引用 简介 移动构造与移动赋值 完美转发 新的类功能 可变 ...
- 深入浅出之C++11新特性
1. auto类型赋予新含义 1.1 auto类型定义 在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的.auto 表示变量是自动存储的,这也是编译 ...
- 《深入理解C++11:C++ 11新特性解析与应用》——导读
前 言 为什么要写这本书 相比其他语言的频繁更新,C++语言标准已经有十多年没有真正更新过了.而上一次标准制定,正是面向对象概念开始盛行的时候.较之基于过程的编程语言,基于面向对象.泛型编程等概念的C ...
- (原创)C++11改进我们的程序之右值引用
http://www.cnblogs.com/qicosmos/p/3369940.html 本次主要讲c++11中的右值引用,后面还会讲到右值引用如何结合std::move优化我们的程序. c++1 ...
- C++11新特性以及std::thread多线程编程
一 .C++11新特性 1. auto 类型推导 1.1 当=号右边的表达式是一个引用类型时,auto会把引用抛弃,直接推导出原始类型: 1.2 当=号右边的表达式带有const属性时,auto不会使 ...
最新文章
- Visual Studio 2005常用插件搜罗
- 网络推广——网络推广专员优化网站有秘诀!
- python导入txt文件并绘图-Python实现读取txt文件中的数据并绘制出图形操作示例
- FSMC(STM32)
- C++的一些知识点摘抄(创建基本类 高级类)
- vue项目职责_进大厂兼职的机会来了!腾讯微校项目招人了!
- Docker和Kubernetes如何让DevOps更具效力
- 关于C++中的pow()函数
- python架构师是做什么的_架构师的工作都干些什么?!想做架构师必看!
- Linux中shell脚本详解
- java mission control_Java Mission Control之使用
- python计算球体体积_漫谈超球体的体积公式
- Arcgis实例学习5--统计直方图、空间分布图、统计信息
- 纽约:高速Wi-Fi将进入大街小巷 时时刻刻可无线上网
- CocoaPods Trunk 发布
- 2019互联网校招薪资表: BAT、华为还没有TMD高
- eclipse打开时报错:
- 培训机构和在线教程还能不能信任?
- 前端websocket连接mqtt服务器(Paho-mqtt,mqttws31.js)以及断开重连
- Html短信导入iphone,苹果短信通讯录如何导入到华为手机?这篇写的超详细!