移动语义和完美转发

前言

c++11中引入了左右值的概念,通常认为具名的,可赋值的变量为左值,不具名的,不可赋值的变量为右值。其中对右值提供了两个实用的函数std::move()和std::forword(),分别被称为移动语义和完美转发,本文我们对这两个函数进行讨论,在讨论之前,我们先了解引用折叠。

引用折叠

c++的编译器按照如下规则进行引用折叠:
引用折叠

移动语义

std::move()通常被称为剪切操作,但个人认为这样称呼其实不太恰当,因为std::move只是将一个左值转换为右值,并不涉及内存的移动,称为剪切还是有些不恰当。我们来g++对看看std::move()的实现。

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

从代码中可以看出,move函数实际上是一种静态转换,先从传入的参数中萃取出参数类型T,然后利用static_cast转换转换左右值类型。另一个问题是为什么函数的参数类型是T&&?这与我们上面介绍的引用折叠有关,假设我们传入的类型是左值,那么参数类型是T&& &=T&,如果我们传入的参数是右值,那么参数类型是T&& &&=T&&,这样就巧妙地保留了我们传入参数的类型。
现在我们已经了解了移动语义的原理和实现,下面我们介绍下移动语义的应用场景。移动语义可以在不对内存进行操作的情况下改变对象的所有权,我们可以通过类似下面的代码调用移动构造函数,这样可以提高程序的效率,实际上stl中的容器也正式这样做的。

class a{
public:
    a():b(0){};
    a(a&& rhs):b(rhs.b){
        cout << "call move construct" << endl;
    };
    a(const a& lhs):b(lhs.b){
        cout << "call copy construct" << endl;
    };
    int b;
};
int main(){
    a A1;
    A1.b = 3;
    a A2(A1);
    a A3(move(A1));
    return 0;
}

下面的图片是代码的运行结果:
在这里插入图片描述

完美转发

移动语义可以将任意引用都转换为右值引用,而完美转发std::forword()的作用则是完美保留原本的类型,即传入的参数是一个左值,那么返回值也是左值;如果我们传入的参数是一个右值,函数将返回右值。下面是std::forward的实现。

  template<typename _Tp>
    inline _Tp&&
    forward(typename std::remove_reference<_Tp>::type& __t) 
    { return static_cast<_Tp&&>(__t); }
 
  template<typename _Tp>
    inline _Tp&&
    forward(typename std::remove_reference<_Tp>::type&& __t) 
    {
      static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
		    " substituting _Tp is an lvalue reference type");
      return static_cast<_Tp&&>(__t);
    }

完美转发有两个参数:_Tp和__t,如果我们需要保持为左值,_Tp应为左值,反之_Tp为右值。与std::move相同,std::forward同样不涉及内存的操作,仅仅只改变对象的所有权。
我们在使用右值时,容易将它传给左值,使变量类型改变,forward则是被设计来解决这种问题的,这在很多地方都有应用,本文不再列出例程。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值