C++11——移动语义
来源:互联网 发布:剑网三 捏脸数据 男 编辑:程序博客网 时间:2024/05/29 18:04
一般我们传递的右值都是临时变量,所以可以随意修改、如果我们知道函数的某个参数是一个右值,就可以将其作为一个临时存储或获取其中的内容,而不会影响程序的正确性。这也就意味着,比起拷贝右值参数的内容,再使用,不如直接使用该右值内容。当动态数组比较大的时候,这样可以节省很多内存分配,提供更多的优化空间。试想,一个函数以vector作为一个参数,就需要将其拷贝进来,而不对原始数据做任何操作。在C++03/98中,我们会采用如下的方法,将这个参数作为一个左值的const引用传入,然后做内存拷贝:
void copy(vector<int> const& vec){ vector<int> v(vec); v.push_back(1);}
1这样就可以将左值或右值传递给该函数了,不过任何情况都是通过拷贝来完成的。如果使用右值引用版本的函数来重载这个函数,这就能避免在传入右值的时候,函数会进行内部拷贝的过程,因为可以任意的对原始值进行修改:
void copy(vector<int> const & vec){ vector<int> v(vec); v.push_back(1);}void copy(vector<int> && vec){ vec.push_back(1);}
如果这个问题存在于类的构造函数中,获取内部右值在新的实例中使用。例如(默认构造函数会分配很大一块内存,在析构函数中释放)。
class X{private: int* data;public: X(): data(new int[1000000]) {} ~X() { delete [] data; } X(const X& other): // 1 data(new int[1000000]) { std::copy(other.data,other.data+1000000,data); } //移动构造函数 X(X&& other): // 2 data(other.data) { other.data=nullptr; }};
一般拷贝构造函数的定义和上面的1一样:分配一块新内存,然后将原来的数据拷贝进来。不过现在有了一个新的构造函数,可以接收右值引用来获取老数据,这就是移动构造函数。在这个例子中,只是将指针拷贝到数据中,并将other以空指针的形式留在了新实例(data)中;使用右值来创建变量,就能避免空间和时间上的多余消耗。
1在有的情况下,有些类型的构造函数只支持移动构造函数,而不支持拷贝构造函数。例如智能指针std::unique_ptr<>的非空实例中,只允许这个指针指向其对象,所以函数在这里就不能用了(如果使用拷贝函数,就会有两个std::unique_ptr<>指向该对象,不满足std::unique_ptr<>定义)。不过,移动构造函数允许对指针的所有权,在实例之间进行传递,并且允许std::unique_ptr<>像一个带有返回值的函数一样使用——指针的转移是通过移动,而非拷贝。
如果你已经知道,某个变量在之后不会再用到了,这个时候你可以显示的移动,通过static_cast
X x1;X x2 = std::move(x1);X x3 = static_cast<X&&>(x2);
想要将参数值不通过拷贝,转化为本地变量或成员变量时,就可以使用这个办法;虽然右值引用参数绑定了右值,不过在函数内部,会当做左值来进行处理:
void do_stuff(X&& x_){ X a(x_); //拷贝 X b(std::move(x_)); //移动}do_stuff(X()); // yes,右值绑定到右值引用上X x;do_stuff(x); // no,左值不能绑定到右值引用上
- C++11——移动语义
- C++11:移动语义
- C++11移动语义探讨——从临时对象到右值引用
- 移动语义
- 移动语义
- C++11 新特性 移动语义
- C++11 移动语义和完美转发
- c++11移动语义右值引用
- C++11:移动语义和完美转发
- [C++] 右值引用:移动语义与完美转发
- C陷阱与缺陷 —— 读书笔记-3、语义“陷阱”
- 【读书笔记】——《HTML5移动开发》语义化的短语元素
- c++移动语义
- 移动语义之我见
- html——语义
- 语义网—RDFS
- C语言编程十大建议——语法语义篇:使用脚本检查部分语义错误
- C++11 新特性(2) 移动语义
- Java四种代码块及运行优先级
- Linux静态库的使用
- 病毒侵袭 HDU
- 求最大公约数
- Hibernate 一级缓存的细节
- C++11——移动语义
- Liner_Shaker_Full
- 递归实例总结
- 内存泄漏及管理(01)-简述GC机制和检测工具
- MySQL数据库最基本的操作
- 实现一个简单的进度条
- windows下用navicat远程链接虚拟机Linux下MySQL数据库
- TCP四次挥手客户端关闭链接为什么要等待2倍MSL
- View事件分发与相关源码解析