欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > c/c++ >内容正文

c/c++

C++11:move移动语义

发布时间:2025/1/21 c/c++ 52 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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移动语义的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。