我是靠谱客的博主 幸福嚓茶,最近开发中收集的这篇文章主要介绍std::forward和std::move源码分析一、右值引用二、forward源码分析三、示例分析四、std::move源码五、参考:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

一、右值引用

二、forward源码分析

三、示例分析

   1、不使用 std::forward

2、用 std::forward

四、std::move源码

五、参考:


一、右值引用

       int和int&是什么?都是类型。int是整数类型,int&则是整数引用类型。同样int&&也是一个类型。两个引号&&是C++ 11提出的一个新的引用类型,右值引用类型,这是一个新的类型。如果你记住这个新类型,那么很多疑问都能迎刃而解。void G(A &&a) ,就很容易明白a是新类型右值引用的一个变量一个值,肯定是一个左值而不是右值。

二、forward源码分析

 /**
   *  @brief  Forward an lvalue.
   *  @return The parameter cast to the specified type.
   *
   *  This function is used to implement "perfect forwarding".
   */
  template<typename _Tp>
    constexpr _Tp&&
    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
    { return static_cast<_Tp&&>(__t); }

  /**
   *  @brief  Forward an rvalue.
   *  @return The parameter cast to the specified type.
   *
   *  This function is used to implement "perfect forwarding".
   */
  template<typename _Tp>
    constexpr _Tp&&
    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
    {
      static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
		    " substituting _Tp is an lvalue reference type");
      return static_cast<_Tp&&>(__t);
    }

对于forward函数

std::forward<T>(u)有两个参数:T与 u。

a. 当T为左值引用类型时,u将被转换为T类型的左值。比如T 为int&

b. 否则u将被转换为T类型右值。比如T为 int ,int &&

三、示例分析

   1、不使用 std::forward

            下述代码G不管传入什么类型的参数,只会最终调用 void F(int& a);

using namespace std;

void F(int& a) {
    cout << "int& version " <<a <<endl;
}

void F(int&& a) {
    // do something
    cout << "int&& version " <<a <<endl;
}

template<class A>
void G(A &&a) {
    F(a); 
}

int main (int argc, char *argv[]) {
    int i = 2;
    G(i); //输出int& version
    G(5); //输出int& version
  return 0; 
}

       G不管传入什么类型的参数,只会最终调用 void F(int& a)

       这是为什么?

        调用G(5)时,A被推导为int类型,但在G内部调用F(a)时,因为G函数中a是一个int &&的变量是个左值,调用F时编译译器自动推断调用 F(int & &&)类型的函数,根据引用折叠原理就会调用F(int & )c++引用折叠_kupePoem的专栏-CSDN博客

      调用G(i)时,A被推导为int &类型,根据引用折叠原理就会调用F(int & )。

2、用 std::forward

    用 std::forward时,G的最终调用出现差异化

using namespace std;

void F(int& a) {
    cout << "int& version " <<a <<endl;
}

void F(int&& a) {
    // do something
    cout << "int&& version " <<a <<endl;
}

template<class A>
void G(A &&a) {
    F(std::forward<A>(a)); 
}

int main (int argc, char *argv[]) {
    int i = 2;
    G(i); //输出int& version
    G(5); //输出int&& version

  return 0; 
}

        调用G(5)时,A被推导为int类型,但在G内部调用F(a)时,因为G函数中a是一个int &&的变量是个左值,调用std::forward<A>(a)(std::forward<int>(a)),A此时为int,强制转换为了右值。

      调用G(i)时,A被推导为int &类型,调用std::forward<A>(a)(std::forward<int&>(a)),还是强制转换成了左值。

四、std::move源码

头文件move.h

  template<typename _Tp>
    constexpr typename std::remove_reference<_Tp>::type&&
    move(_Tp&& __t) noexcept
    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

     可以看出std::move也是进行了强制类型转换,把一个左值强制转换成右值,没有新奇之处,参数__t的类型是万能引用(CSDN),可以接受不同类型的参数。

using namespace std;

void F(int& a) {
    cout << "int& version " <<a <<endl;
}

void F(int&& a) {
    // do something
    cout << "int&& version " <<a <<endl;
}

template<class A>
void G(A &&a) {
    F(std::forward<A>(a)); 
}

int main (int argc, char *argv[]) {
    int i = 2;
    G(std::move(i)); //输出int&& version
    G(5); //输出int&& version

  return 0; 
}

五、参考:

引用折叠和完美转发 - 知乎

如何理解c++中的引用折叠? - 知乎

C++ 11 右值引用以及std::move_luotuo44的专栏-CSDN博客

一文读懂C++右值引用和std::move_kupePoem的专栏-CSDN博客

最后

以上就是幸福嚓茶为你收集整理的std::forward和std::move源码分析一、右值引用二、forward源码分析三、示例分析四、std::move源码五、参考:的全部内容,希望文章能够帮你解决std::forward和std::move源码分析一、右值引用二、forward源码分析三、示例分析四、std::move源码五、参考:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部