[C++11] 移动语义和完美转发

移动语义

仅仅转移资源的所有者,将资源的拥有者改为被赋值者,这就是所谓的移动语义,可以避免无谓的深拷贝,以提高性能。
C++中的所有容器都实现了移动语义,方便我们实现性能优化。

A& A::operator=(const A&& rhs) {
              // 转移资源的控制权,无需复制
}

如何应用移动语义?
1.通过右值引用匹配临时值。
2.通过std::move方法将一个左值强制转换为右值引用。

std::move只是转移了资源的控制权,本质上是将左值变成右值引用,以用于移动语义,避免含有资源的的对象发生无谓的拷贝。
std::move对于拥有形如对内存、文件句柄等资源的成员的对象有效。如果是一些基本类型,比如int、char[10]数组等,实际上仍会发生拷贝,因为没有对应的移动构造函数,所以说std::move对于含有资源的对象更有意义。std::string有移动构造函数,但是经过测试,只有在string长度大于阈值(在堆上构建)才会调用移动构造函数。

完美转发

右值引用类型是独立于值的,一个右值引用参数作为函数的形参,在函数内部在转发该参数的时候它已经变成一个左值了,并不是它原来的类型了,比如:

void notPerfectForward(int&& i) {
  printValue(i);    //  i是一个具名的对象,编译器会当做左值处理
}

因此我们需要一种方法能够按照参数原本的类型转发到另一个函数,这种转发被称为完美转发。
所谓的完美转发(Perfect Forwarding),是指在函数模板中,完全依照模板的参数的类型(即保持参数的左值、右值特征),将参
数传递给函数模板中调用的另一个函数。

template<typename T>
void perfectForward(T &&t) {
    printValue(std::forward<T>(t));
}

完美转发也不一定只用于函数模板:

Data p;
Data && p1 = std::move(p);
func(std::forward<Data>(p1)); // OK
 
void func_1(Data && data)
{
   func(std::forward<Data>(data));
} 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容