C++右值引用与转移语义简要介绍
在 C++11 之前,值类型变量的传递会导致把它完整的拷贝一份
比如说把一个 vector 作为函数返回值赋值给某个局部变量,他就会调用 vector 的拷贝构造函数创建一个完整的副本,把这个副本作为函数返回的临时变量,然后把这个临时变量赋值给那个局部变量时又会再次拷贝构造
(不过这其实会被大多数编译器优化掉)
右值
上面例子中的临时变量就是一个右值
右值是无法获取到地址的值
大概可以理解为临时的变量或者没有被声明但是实际存在的变量
函数的返回值,还有常量都是右值
右值引用
根据名字我们知道它是一个右值的引用(废话)
使用右值引用接收右值可以让右值不被销毁,同时也不会拷贝任何数据
举个例子,下面代码中 str 变量接收了 GetStr 函数返回的右值
string GetStr() {
return "Hello world";
}
int main() {
string&& str = GetStr();
return 0;
}
转移构造函数
因为右值被使用过后就会被销毁,所以完整拷贝它的备份是很不划算的
我们希望把右值里的数据直接偷出来
那么我们可以通过转移构造函数来实现
class Array {
private:
int* arr;
int len;
public:
Array(int len) : arr(new int[len]) {}
~Array() {
if (arr) delete[] arr;
}
Array(const Array& other) : len(other.len) {
// 拷贝构造会导致整个数组被复制
arr = new int[other.len];
memcpy(arr, other.arr, len * sizeof(int));
}
Array(Array&& other) : arr(other.arr) {
// 转移构造可以直接把数组的指针偷过来
other.arr = NULL;
}
};
可以看到上面的代码把 other 这个右值里的 arr 偷走了
另外类似的还有转移赋值函数,也是使用右值引用传参,然后在函数里把右值里的东西偷出来
转移语义
那么又有一个问题,如果有一个左值,他以后不会再被用到,我希望能把它里面的东西偷出来放到另一个左值里,怎么实现
使用 std::move,把一个左值转换为右值,然后把它里面存的东西搬空
看这个例子就很清晰了
class Array {
private:
int* arr;
int len;
public:
Array(int len) : arr(new int[len]) {}
~Array() {
if (arr) delete[] arr;
}
Array(const Array& other) : len(other.len) {
// 拷贝构造会导致整个数组被复制
arr = new int[other.len];
memcpy(arr, other.arr, len * sizeof(int));
}
Array(Array&& other) : arr(other.arr) {
// 转移构造可以直接把数组的指针偷过来
other.arr = NULL;
}
};
int main() {
Array a(100);
Array b(move(a));
return 0;
}
可以看到变量 a 里存的数组指针被变量 b 偷出来了,从而避免了整个数组的拷贝
C++右值引用与转移语义简要介绍的更多相关文章
- 【转】C++11 标准新特性: 右值引用与转移语义
VS2013出来了,对于C++来说,最大的改变莫过于对于C++11新特性的支持,在网上搜了一下C++11的介绍,发现这篇文章非常不错,分享给大家同时自己作为存档. 原文地址:http://www.ib ...
- C++11 标准新特性: 右值引用与转移语义
文章出处:https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ 新特性的目的 右值引用 (Rvalue Referene) ...
- C++11 右值引用和转移语义
新特性的目的 右值引用 (Rvalue Referene) 是 C++ 新标准 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它实现了转移语义 (Move Sementics) 和 ...
- C++11 右值引用 与 转移语义
新特性的目的 右值引用(R-value Reference)是C++新标准(C++11, 11代表2011年)中引入的新特性,它实现了转移语义(Move Semantics)和精确传递(Perfect ...
- C++右值引用与转移语义
std::forwad? C++11 中定义的 T&& 的推导规则为: 右值实参为右值引用,左值实参仍然为左值引用. 参考: 右值引用与转移语义
- 右值引用与转移语义(C++11)
参考资料: http://www.cnblogs.com/lebronjames/p/3614773.html 左值和右值定义: C++( 包括 C) 中所有的表达式和变量要么是左值,要么是右值.通俗 ...
- C++11新特性:右值引用和转移构造函数
问题背景 #include <iostream> using namespace std; vector<int> doubleValues (const vector< ...
- C++11新特性之右值引用(&&)、移动语义(move)、完美转换(forward)
1. 右值引用 个人认为右值引用的目的主要是为了是减少内存拷贝,优化性能. 比如下面的代码: String Fun() { String str = "hello world"; ...
- [c++11]右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
- [转][c++11]我理解的右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
随机推荐
- Windows文件句柄无效
今天我用FreeFileSync从移动硬盘复制一个名为Con的文件夹到本地硬盘,复制失败. 通过文件夹资源管理器Explorer直接访问文件夹则提示"禁止访问",右键属性切换到安全 ...
- 总结(3)--- 知识总结(内存管理、线程阻塞、GIL锁)
一.Python中是如何进行内存管理的? 垃圾回收:Python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值.对Python而言,对象的类型和内存都是在运行时确定的 ...
- 解锁 ElasticJob 云原生实践的难题
发生了什么 最近在逛 ElasticJob 官方社区时发现很多小伙伴都在头疼这个 ElasticJob 上云的问题,ElasticJob 本就号称分布式弹性任务调度框架,怎么在云原生环境就有了问题了呢 ...
- 【Javaweb】了解link标签
link标签的属性 标签就是定义文档和外部的关系,常见用途是链接样式表.通常指存在于head部分. 规定被连接文档的位置 <link rel='stylesheet' href='./ease. ...
- 28、错误error
1.是什么? 在实际的项目中,我们希望通过程序的错误信息快速定位问题,但是又不喜欢错误处理:代码就会很冗余又啰嗦.Go语言没有提供类似Java.C#语言中的try...catch异常处理方法,而是通过 ...
- oracle12c静默安装
oracle12c 静默安装 先决条件 ● 至少 1 GB RAM 用于 Oracle 数据库安装.建议使用 2 GB 内存. ● 至少 8 GB RAM 用于 Oracle Grid Infrast ...
- 香橙派5plus从ssd启动Ubuntu
官方接口图 我实际会用到的就几个接口,背面的话就一个M.2固态的位置: 其中WIFI模块的接口应该也可以插2230的固态,不过是pcie2.0的速度,背面的接口则是pcie3.0*4的速度,差距还是挺 ...
- idea2020下载、安装、破解、配置
idea2020下载.安装.破解.配置 idea2020下载 [推荐]官方下载地址:https://www.jetbrains.com/idea/download/other.html 进入后往下找, ...
- 神经网络优化篇:详解梯度的数值逼近(Numerical approximation of gradients)
在实施backprop时,有一个测试叫做梯度检验,它的作用是确保backprop正确实施.因为有时候,虽然写下了这些方程式,却不能100%确定,执行backprop的所有细节都是正确的.为了逐渐实现梯 ...
- Python——第二章:基础数据类型
下面是需要掌握的知识点: int, float, bool (5星)str (5星)list (5星)tuple (2星)set (1星)dict (5星)bytes ...