资源转移和完美转发

一、std::move

在C++11中添加了右值引用,并且不能使用左值初始化右值引用,如果想要使用左值初始化一个右值引用需要借助std::move()函数,使用std::move方法可以将左值转化为右值。使用这个函数并不能移动任何东西,而是和移动构造函数一样具有移动语义,将对象的状态或者所有权从一个对象移动到另一个对象上,只是转移,没有内存拷贝。

从实现上讲,std::move基本等同于一个类型转换:static_cast(lvalue);函数原型如下:

template<class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) _NOEXCEPT
{	// forward _Arg as movable
    return (static_cast<remove_reference_t<_Ty>&&>(_Arg));
}

使用方法如下:

class Test
{
publicTest(){}
    /*TODO*/
}
int main()
{
    Test t;
    Test && v1 = t;          // error
    Test && v2 = move(t);    // ok
    return 0;
}
  • Test && v1 = t,这段代码使用左值初始化右值,语法错误。
  • Test && v2 = move(t),使用move()方法将左值转化为右值,因此可以使用右值引用。

假设一个临时容器很大,并且需要将这个容器赋值给另一个容器,就可以执行如下操作:

vector<string> vec;
vec.push_back("hello");
vec.push_back("world");
vector<string> vec2 = vec;        // 需要深拷贝, 效率低
vector<string> vec3 = move(vec);

如果不使用std::move,拷贝的代价很大,性能较低。使用move几乎没有任何代价,只是转换了资源的所有权,如果一个对象内部有较大的堆内存或者动态数组时,使用move就可以非常方便的进行数据所有权的转移。另外,我们也可以给类编写相应的移动构造函数(T::T(T&&another))和具有移动语义的赋值函数(T&&T::operator=(T&&rhs)),在构造对象和赋值的时候尽可能的进行资源的重复利用,因为它们都是接收一个右值引用参数。

二、std::forward

右值引用类型是独立于值的,一个右值引用作为函数的形参时,在函数内部转发该参数给内部其他函数时,它就变成了一个左值,并不是原来的类型了。如果需要按照原来的类型转发到另一个函数,可以使用C++11提供的std::forward函数,该函数实现的功能称之为完美转发。

// 函数原型
template <class T> T&& forward (typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& t) noexcept;

// 精简之后的样子
std::forward<T>(t);
  • 当T为左值引用类型时,t将被转化为T类型的左值。
  • 当T不是左值引用类型时,t将被转化为T类型的右值。

下面是一个例子演示如何使用std::forward,代码如下:

#include <iostream>
using namespace std;

template<typename T>
void printValue(T& t)
{
    cout << "l-value: " << t << endl;
}

template<typename T>
void printValue(T&& t)
{
    cout << "r-value: " << t << endl;
}

template<typename T>
void testForward(T && v)
{
    printValue(v);
    printValue(move(v));
    printValue(forward<T>(v));
    cout << endl;
}

int main()
{
    testForward(520);
    int num = 1314;
    testForward(num);
    testForward(forward<int>(num));
    testForward(forward<int&>(num));
    testForward(forward<int&&>(num));

    return 0;
}

测试代码的结果:

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值