右值引用、std::move()

2017-11-07  本文已影响0人  Myth52125

参考文章

模板参数的右值引用形参

template <typename T>
void f5(T&&);

当函数是一个模板函数的时候,当他的形参是右值引用的时候有如下的不同:

传入左值,传入值的类型被推断为类型的引用
比如,传入string类型,那么T被推断为string&
同时,引用折叠:怎么说,意思就是左值引用的引用就等于引用,也是是,所有的双数引用可以折叠为右值引用。
而所有单数的引用可以折叠为左值引用

T&& && &&=T&&
T&& && && & =T&

因此,综上棉量两点:
当T = string &&是,传入的参数类型为string& &&,因此被折叠为string &。
这就是模板函数的右值引用形参可以接受一个左值的原因。

普通函数的右值引用形参

stl大量的使用了type_traits技术来提取参数类型

例如std::move()

template <class _Ty>
inline constexpr typename remove_reference<_Ty>::type &&
move(_Ty &&_Arg) _NOEXCEPT
{ // forward _Arg as movable
    return (static_cast<typename remove_reference<_Ty>::type &&>(_Arg));
}

remove_reference<_Ty>

template <class _Ty>
struct remove_reference
{ // remove reference
    typedef _Ty type;
};

template <class _Ty>
struct remove_reference<_Ty &>
{ // remove reference
    typedef _Ty type;
};

template <class _Ty>
struct remove_reference<_Ty &&>
{ // remove rvalue reference
    typedef _Ty type;
};

因此remove_reference能够根据传入参数的不同,在其typedef _Ty type中萃取出传入的类型。
std::move中的static_cast<typename remove_reference<_Ty>::type &&>(_Arg)进行类型转换。

步骤是:根据传入的参数,萃取出参数的类型,然后转化为参数的右值引用类型。

编译器行为

现在的编译器基本上都会做返回值优化(return value optimization)。也就是说,编译器会在函数返回的地方直接创建对象,而不是在函数中创建后再复制出来。很明显,这比move语义还要好一点。

这也就是为什么有的时候,栈参数的地址比函数内对象的地址还要低。因为要返回的对象被直接创建在返回值处。

上一篇 下一篇

猜你喜欢

热点阅读