目录

1. C++move的概念

2. C++move的特点

3. 左值、右值与左值引用、右值引用

3.1 左值和右值的概念

3.2 左值引用和右值引用

4. std::move详解

4.1 std::move简介

4.2 std::move详解

4.3 std::move实现:

4.4 std::move的优点

4.5  std::move的使用


参考:

https://blog.csdn.net/s11show_163/article/details/114296006

https://blog.csdn.net/daaikuaichuan/article/details/88371948
https://zhuanlan.zhihu.com/p/94588204
https://www.cnblogs.com/SZxiaochun/p/8017475.html
https://www.cnblogs.com/yoyo-sincerely/p/8658075.html
左值引用与右值引用,以及为什么右值引用本身是左值的问题详见:https://www.cnblogs.com/char-cheng/p/11026936.html

1. C++move的概念

一句话概括std::move ———— std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。

2. C++move的特点

  1. std::move函数可以以非常简单的方式将左值引用转换为右值引用。(左值、左值引用、右值、右值引用 参见:http://www.cnblogs.com/SZxiaochun/p/8017475.html)
  2. 通过std::move,可以避免不必要的拷贝操作。
  3. std::move是为性能而生。
  4. std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。
  5. 如string类在赋值或者拷贝构造函数中会声明char数组来存放数据,然后把原string中的 char 数组被析构函数释放,如果a是一个临时变量,则上面的拷贝,析构就是多余的,完全可以把临时变量a中的数据直接 “转移” 到新的变量下面即可。

3. 左值、右值与左值引用、右值引用

右值引用(及其支持的Move语意和完美转发)是C++0x加入的最重大语言特性之一。从实践角度讲,它能够完美解决C++中长久以来为人所诟病的临时对象效率问题。从语言本身讲,它健全了C++中的引用类型在左值右值方面的缺陷。从库设计者的角度讲,它给库设计者又带来了一把利器。从库使用者的角度讲,不动一兵一卒便可以获得“免费的”效率提升。

3.1 左值和右值的概念

  1. 左值是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体;
  2. 右值当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存器。
  3. 一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。
  4. 左值:指表达式结束后依然存在的持久对象,可以取地址,具名变量或对象 。
  5. 右值:表达式结束后就不再存在的临时对象,不可以取地址,没有名字。
int a;
int b;a = 3;
b = 4;
a = b;
b = a;// 以下写法不合法。
3 = a;
a + b = 4;

3.2 左值引用和右值引用

引用是C++语法做的优化,引用的本质还是靠指针来实现的。引用相当于变量的别名。引用可以改变指针的指向,还可以改变指针所指向的值。

左值引用:type &引用名 = 左值表达式;就是对左值的引用 就是给左值取别名

右值引用:type &&引用名 = 右值表达式;就是对右值的引用 就是给右值取别名

int a=10;            //a 是左值
double b=1.3;       //b 是左值
//左值引用
int & Ta=a;            //引用左值   故 是一个左值引用
double & Tb=b;     //引用左值 故是一个左值引用

再比如:

int a = 100;
int&& b = 100;//右值引用
int& c = b; //正确,b为左值
int& d = 100; //错误

4. std::move详解

4.1 std::move简介

在C++11中,标准库在中提供了一个有用的函数std::move,std::move并不能移动任何东西,它唯一的功能是将一个左值引用强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义。从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue);

#include <iostream>
#include <utility>
#include <vector>
#include <string>
int main()
{std::string str = "Hello";std::vector<std::string> v;//调用常规的拷贝构造函数,新建字符数组,拷贝数据v.push_back(str);std::cout << "After copy, str is \"" << str << "\"\n"; //str输出为"Hello"//调用移动构造函数,掏空str,掏空后,最好不要使用strv.push_back(std::move(str));std::cout << "After move, str is \"" << str << "\"\n"; //str输出为空std::cout << "The contents of the vector are \"" << v[0]<< "\", \"" << v[1] << "\"\n";//v[0]、v[1]都为"Hello"
}

输出

After copy, str is "Hello"
After move, str is ""
The contents of the vector are "Hello", "Hello"

4.2 std::move详解

std::move 的函数原型定义:

template <typename T>
typename remove_reference<T>::type&& move(T&& t)
{return static_cast<typename remove_reference<T>::type &&>(t);
}

首先,函数参数T&&是一个指向模板类型参数的右值引用,通过引用折叠,此参数可以与任何类型的实参匹配(可以传递左值或右值,这是std::move主要使用的两种场景)。关于引用折叠如下:

所有右值引用折叠到右值引用上仍然是一个右值引用。(A&& && 变成 A&&) 。
所有的其他引用类型之间的折叠都将变成左值引用。 (A& & 变成 A&; A& && 变成 A&; A&& & 变成 A&)。

简单来说,右值经过T&&传递类型保持不变还是右值,而左值经过T&&变为普通的左值引用。

//原始的,最通用的版本
template <typename T> struct remove_reference{typedef T type;  //定义T的类型别名为type
};//部分版本特例化,将用于左值引用和右值引用
template <class T> struct remove_reference<T&> //左值引用
{ typedef T type; }template <class T> struct remove_reference<T&&> //右值引用
{ typedef T type; }   //举例如下,下列定义的a、b、c三个变量都是int类型
int i;
remove_refrence<decltype(42)>::type a;             //使用原版本,
remove_refrence<decltype(i)>::type  b;             //左值引用特例版本
remove_refrence<decltype(std::move(i))>::type  b;  //右值引用特例版本 

4.3 std::move实现:

1. 首先,通过右值引用传递模板实现,利用引用折叠原理将右值经过T&&传递类型保持不变还是右值,而左值经过T&&变为普通的左值引用,以保证模板可以传递任意实参,且保持类型不变。(cpr:先能够把参数类型全都接收)
2. 然后我们通过static_cast<>进行强制类型转换返回T&&右值引用,而static_cast之所以能使用类型转换,是通过remove_refrence::type模板移除T&&,T&的引用,获取具体类型T(模板偏特化)。(cpr:再把接收的参数的原引用抹除强转成右引)

4.4 std::move的优点

std::move语句可以将左值变为右值而避免拷贝构造。

std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝。

4.5  std::move的使用

比如向vector中插入新元素。

int a = 1;
vector<int> vec;
vec.push_back(move(a));

详解C++移动语义std::move()相关推荐

  1. 百度AI开发者大会百度大脑论坛:详解“多模态深度语义理解”

    7月4日召开的百度AI开发者大会(Baidu Create 2018)上,百度高级副总裁.AI技术平台体系(AIG)总负责人王海峰发布百度大脑3.0,并指出,百度大脑3.0的核心是"多模态深 ...

  2. UNIX(多线程):19---Future 类型详解

    Future 类型详解 本文主要介绍 std::future,std::shared_future 以及 std::future_error,另外还会介绍 <future> 头文件中的 s ...

  3. 主成分分析(PCA)——matlab程序及函数详解

    参考来源: http://www.cnblogs.com/Hand-Head/articles/5156435.html http://www.matlabsky.com/thread-11751-1 ...

  4. c++ std::move详解

    c++ std::move详解 在移动构造中的时候,移动拷贝其实就是把原来参数对象的指针地址给到了构造的对象,再把原先对象的指针置为NULL,这样内存就不会被原来函数给析构了.对于实体的对象执行的其实 ...

  5. std::move作用详解

    C++11右值引用和std::move语句实例解析 关键字:C++11,右值引用,rvalue,std::move,VS 2015 OS:Windows 10 右值引用(及其支持的Move语意和完美转 ...

  6. C++11 并发指南四(future 详解二 std::packaged_task 介绍)

    上一讲<C++11 并发指南四(<future> 详解一 std::promise 介绍)>主要介绍了 <future> 头文件中的 std::promise 类, ...

  7. C++11 并发指南四(future 详解一 std::promise 介绍)

    前面两讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread 和 std::m ...

  8. C++11 并发指南------std::thread 详解

    参考: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Int ...

  9. C++11 并发指南三(std::mutex 详解)

    上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法. Mutex ...

最新文章

  1. 【直播】林锦弘:CV赛事高分经验分享
  2. 没有这 29 款插件的 Chrome 是没有灵魂的!
  3. 初识FPGA(一)(初步介绍FPGA)
  4. Dropout和网络结构实现数据增广带来的不同影响分析
  5. 一款WP小游戏代码分享
  6. 梯度与梯度下降法详解
  7. 四大触点,教你从“用户视角”构建数据分析体系
  8. prettytensor 的使用
  9. 中文路径读取乱码,json乱码
  10. Qt的project文件的设置相关
  11. ipad无法加入网络怎么办?
  12. 中国企业软件25年到底有几次颠覆
  13. OpenCV实践(4)- 叠加两幅图片
  14. 在直播软件搭建中,如何基于rtmp实现视频直播?
  15. WPF 使用 Direct2D1 画图入门
  16. ABAP tRFC和qRFC
  17. atom 编辑器html,Atom编辑器配置
  18. html5定义一个变量,JavaScript 变量
  19. windows下测试磁盘读写(HD Tune)
  20. 元胞自动机 C实现 + OpenCV界面

热门文章

  1. bootstrap官网
  2. Unity架构有点乱
  3. 博弈之 取石子1——6)
  4. Linux 系统内存分析
  5. 确保字符串的每个单词首字母都大写,其余部分小写
  6. tablelayout的使用
  7. SSD固态存储大观(二)
  8. MySQL HINT:Straight_JOIN
  9. 最优二叉树——哈夫曼树
  10. [转]java中byte转换int时为何与0xff进行与运算