📂C/C++
🔖C++
2022-04-05 16:07阅读: 118评论: 0推荐: 0

std::move()与std::forward()探究

move与forward函数探究

详情参见书《C++ primer》P608-P614

1.std::move()

copy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
#include<type_traits> template<typename T> typename std::remove_reference<T>::type&& move(T&& t) { return static_cast<typename std::remove_reference<T>::type&&>(t); }

从上述std::move()代码可以看到,该函数为一个模板。可以接受任何类型的参数,返回传入值的右值引用

  • 函数内容分析

    • typename remove_reference<T>::type中的typename是显式的告诉编译器这是一个类型,因为C++默认通过域作用符访问的名字不是类型。

      • remove_reference在头文件type_traits中,返回T的原始类型,可参考网址。属于模版元编程范围,在编译期执行,非运行期
      copy
      • 1
      • 2
      • 3
      • 4
      • 5
      //在编译期执行 结果都是int类型 std::remove_reference<int>::type std::remove_reference<int&>::type std::remove_reference<int&&>::type std::remove_reference<const int&>::type
    • static_cast 转换成指定的右值引用类型。可以将一个左值强制转换成右值引用

  • 如何工作:

    • 因为参数是一个右值引用类型,所以可以传递一个右值。如 string s1 = std::move(string("hello")),T就会被推断为string
    • 当传入一个左值时,如string s2 = std::move(s1),T会被推断为string &,函数参数 t 就会推断为string& &&类型,根据引用折叠规则,t 最终为string &类型。注意,赋值之后s1的值是不确定的。
      • 当将一个左值传递给函数的右值引用参数时,且此右值引用指向为模板类型参数(T&&)时,编译器会推断模板类型参数为实参的左值引用类型
  • 模板参数类型的引用折叠:当我们使用类型别名或模板类型参数间接(不能直接)创建一个引用的引用时,会发生折叠。

    • 只有右值引用的右值引用会折叠成右值引用,其他全折叠成左值引用。
    • T& &, T&& &, T& && 都折叠成 T&。
    • T&& && 折叠成 T&&。
  • 模版元编程(template metaprogram),是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。

    • 不同于普通的运行期程序,模版元程序的执行完全是在编译期。
    • 模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改。
    • 用到的语法元素也是相当有限,不能使用运行期的一些语法,比如if-else、for等语句都不能用。

2.std::forward()

  • 在某些情况下,需要将一个或者多个实参连同类型不变地转发给其他函数,需要保持被转发实参的所有性质,包括是否是const以及是左值还是右值。实现完美转发。
  • 必须显示模板实参来调用。
copy
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
#include<type_traits> template <typename T> T&& forward(typename std::remove_reference<T>::type& param) { return static_cast<T&&>(param); } template <typename T> T&& forward(typename std::remove_reference<T>::type&& param) { return static_cast<T&&>(param); }
  • 有两个函数模板,接受左值就返回左值,接受右值就返回右值。

  • 当param为左值引用时,调用第一个函数,推导得 T = X&T&&展开为X& &&,经过引用折叠后得到X&,将返回左值引用即最后返回static_cast<X&>(param)

  • 当param为左值时,调用第一个函数,T 就是普通(非引用)类型T = X,将返回右值引用即最后返回static_cast<X&&>(param)。此时作用类似std::move(),但与move函数不建议使用原对象不同,可以继续使用。

  • 当param是右值引用时,调用第二个函数,此时推到得到T = X&&,则T&&展开为X&& &&,经过引用折叠后得到X&&,将返回右值引用即最后返回static_cast<X&&>(param)

  • 当param是右值时,调用第二个函数,T 就是普通(非引用)类型T = X,将返回右值引用即最后返回static_cast<X&&>(param)

本文作者:oniisan

本文链接:https://www.cnblogs.com/oniisan/p/moveFunction.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Oniisan_Rui  阅读(118)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起