C++11:move移动语义
前言
我们知道移动语义是通过右值引用来匹配临时值,那么,普通的左值是否也能借助移动语义来优化性能呢,C++11为了解决这个问题,提供了std::move方法来将左值转换成右值。
正文
move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存拷贝。
move实际上并不能移动任何东西,它只是将一个左值强制转换成一个右值引用,使我们可以通过右值引用使用该值,以用于移动语义,强制转换为右值的目的是为了方便实现移动构造。
这种move语义是很有用的,比如一个对象中有一些指针资源或者动态数组,在对象的赋值或者拷贝时就不需要拷贝这些资源了。在C++11之前拷贝构造函数和赋值函数可能要像下面这样定义。假设A对象内部有一个资源m_ptr:
A & A::operator=(const A &rhs) { //销毁m_ptr指向的资源 //复制rhs.m_ptr所指向的资源,并使m_ptr指向它 }通过A的拷贝构造函数也是这样,假设这样来使用A:
A foo(); A a; a = foo();最后一行将会发生如下操作:
- 销毁a所持有的资源
- 复制foo返回的临时对象所拥有的资源
- 销毁临时对象,释放其资源
上面的办法是可行的,但是更有效的方法是直接交换a和临时对象中的资源指针,然后让临时对象的析构函数去销毁a原来拥有的资源。当复制操作符的右边是右值的时候,我们希望赋值操作符被定义成下面这样:
A & A::operator=(const A &&rhs) { //转移资源的控制权,无需复制 }仅仅转移资源的所有者,将资源的拥有者改为被赋值者,这就是move语义。
如下示例,假设一个临时容器很大,赋值给另一个容器:
{std::list<std::string> arrs; //省略初始化std::list<std::string> temp = arrs; }std::list<std::string> arrs; std::list<std::string> temp = std::move(arrs);如果这里不用move,拷贝的代价很大,性能较低。而使用move几乎没有任何代价,只是将资源的所有权转移了,实际上是将左值变成了右值引用,然后应用move语义调用构造函数,这样避免了拷贝,提高程序性能。
当一个对象内部有较大的堆内存或者动态数组时,很有必要写move语义的拷贝构造函数和赋值函数,避免无谓的深拷贝,以提高性能。
注意:move对于拥有形如对内存、文件句柄等子资源的成员的对象有效,如果是一些基本类型, 如int和char[4]数组时,如果使用move,仍然会发生拷贝(因为没有对应的移动构造函数),所以说move对于含资源的对象来说更有意义。
参考:《深入应用C++11》
总结
以上是生活随笔为你收集整理的C++11:move移动语义的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Coding:在数组中查找具有给定总和的
- 下一篇: C++之仿函数简介