std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg is an lvalue reference, the function returns arg without modifying its type.

std::forward:This is a helper function to allow perfect forwarding of arguments taken as rvalue references to deduced types, preserving any potential move semantics involved.

std::forward<T>(u)有两个参数:T 与 u。当T为左值引用类型时,u将被转换为T类型的左值,否则u将被转换为T类型右值。如此定义std::forward是为了在使用右值引用参数的函数模板中解决参数的完美转发问题。

std::move是无条件的转为右值引用,而std::forward是有条件的转为右值引用,更准确的说叫做Perfect forwarding(完美转发),而std::forward里面蕴含着的条件则是Reference Collapsing(引用折叠)。

std::move不move任何东西。std::forward也不转发任何东西。在运行时,他们什么都不做。不产生可执行代码,一个比特的代码也不产生。

std::move和std::forward只是执行转换的函数(确切的说应该是函数模板)。std::move无条件的将它的参数转换成一个右值,而std::forward当特定的条件满足时,才会执行它的转换。

std::move表现为无条件的右值转换,就其本身而已,它不会移动任何东西。 std::forward仅当参数被右值绑定时,才会把参数转换为右值。 std::move和std::forward在运行时不做任何事情。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

  1. #include "forward.hpp"
  2. #include <utility>
  3. #include <iostream>
  4. #include <memory>
  5. #include <string>
  6. //////////////////////////////////////////////
  7. // reference: http://en.cppreference.com/w/cpp/utility/forward
  8. struct A {
  9. A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; }
  10. A(int& n)  { std::cout << "lvalue overload, n=" << n << "\n"; }
  11. };
  12. class B {
  13. public:
  14. template<class T1, class T2, class T3>
  15. B(T1&& t1, T2&& t2, T3&& t3) :
  16. a1_{ std::forward<T1>(t1) },
  17. a2_{ std::forward<T2>(t2) },
  18. a3_{ std::forward<T3>(t3) }
  19. {
  20. }
  21. private:
  22. A a1_, a2_, a3_;
  23. };
  24. template<class T, class U>
  25. std::unique_ptr<T> make_unique1(U&& u)
  26. {
  27. return std::unique_ptr<T>(new T(std::forward<U>(u)));
  28. }
  29. template<class T, class... U>
  30. std::unique_ptr<T> make_unique(U&&... u)
  31. {
  32. return std::unique_ptr<T>(new T(std::forward<U>(u)...));
  33. }
  34. int test_forward1()
  35. {
  36. auto p1 = make_unique1<A>(2); // rvalue
  37. int i = 1;
  38. auto p2 = make_unique1<A>(i); // lvalue
  39. std::cout << "B\n";
  40. auto t = make_unique<B>(2, i, 3);
  41. return 0;
  42. }
  43. ////////////////////////////////////////////////////////
  44. // reference: http://www.cplusplus.com/reference/utility/forward/
  45. // function with lvalue and rvalue reference overloads:
  46. void overloaded(const int& x) { std::cout << "[lvalue]"; }
  47. void overloaded(int&& x) { std::cout << "[rvalue]"; }
  48. // function template taking rvalue reference to deduced type:
  49. template <class T> void fn(T&& x) {
  50. overloaded(x);                   // always an lvalue
  51. overloaded(std::forward<T>(x));  // rvalue if argument is rvalue
  52. }
  53. int test_forward2()
  54. {
  55. int a;
  56. std::cout << "calling fn with lvalue: ";
  57. fn(a);
  58. std::cout << '\n';
  59. std::cout << "calling fn with rvalue: ";
  60. fn(0);
  61. std::cout << '\n';
  62. return 0;
  63. }
  64. //////////////////////////////////////////////////////
  65. // reference: http://stackoverflow.com/questions/8526598/how-does-stdforward-work
  66. template<class T>
  67. struct some_struct{
  68. T _v;
  69. template<class U>
  70. some_struct(U&& v) : _v(static_cast<U&&>(v)) {} // perfect forwarding here
  71. // std::forward is just syntactic sugar for this
  72. };
  73. int test_forward3()
  74. {
  75. /* remember the reference collapsing rules(引用折叠规则):
  76. 前者代表接受类型,后者代表进入类型,=>表示引用折叠之后的类型,即最后被推导决断的类型
  77. TR   R
  78. T&   &->T&   // lvalue reference to cv TR -> lvalue reference to T
  79. T&   &&->T&  // rvalue reference to cv TR -> TR (lvalue reference to T)
  80. T&&  &->T&   // lvalue reference to cv TR -> lvalue reference to T
  81. T&&  &&->T&& // rvalue reference to cv TR -> TR (rvalue reference to T) */
  82. some_struct<int> s1(5);
  83. // in ctor: '5' is rvalue (int&&), so 'U' is deduced as 'int', giving 'int&&'
  84. // ctor after deduction: 'some_struct(int&& v)' ('U' == 'int')
  85. // with rvalue reference 'v' bound to rvalue '5'
  86. // now we 'static_cast' 'v' to 'U&&', giving 'static_cast<int&&>(v)'
  87. // this just turns 'v' back into an rvalue
  88. // (named rvalue references, 'v' in this case, are lvalues)
  89. // huzzah, we forwarded an rvalue to the constructor of '_v'!
  90. // attention, real magic happens here
  91. int i = 5;
  92. some_struct<int> s2(i);
  93. // in ctor: 'i' is an lvalue ('int&'), so 'U' is deduced as 'int&', giving 'int& &&'
  94. // applying the reference collapsing rules yields 'int&' (& + && -> &)
  95. // ctor after deduction and collapsing: 'some_struct(int& v)' ('U' == 'int&')
  96. // with lvalue reference 'v' bound to lvalue 'i'
  97. // now we 'static_cast' 'v' to 'U&&', giving 'static_cast<int& &&>(v)'
  98. // after collapsing rules: 'static_cast<int&>(v)'
  99. // this is a no-op, 'v' is already 'int&'
  100. // huzzah, we forwarded an lvalue to the constructor of '_v'!
  101. return 0;
  102. }
  103. ////////////////////////////////////////////////////
  104. // reference: https://oopscenities.net/2014/02/01/c11-perfect-forwarding/
  105. void sum(int a, int b)
  106. {
  107. std::cout << a + b << std::endl;
  108. }
  109. void concat(const std::string& a, const std::string& b)
  110. {
  111. std::cout<< a + b << std::endl;
  112. }
  113. void successor(int a, int& b)
  114. {
  115. b = ++a;
  116. }
  117. template <typename PROC, typename A, typename B>
  118. void invoke(PROC p, A&& a, B&& b)
  119. {
  120. p(std::forward<A>(a), std::forward<B>(b));
  121. }
  122. int test_forward4()
  123. {
  124. invoke(sum, 10, 20);
  125. invoke(concat, "Hello", "world");
  126. int s = 0;
  127. invoke(successor, 10, s);
  128. std::cout << s << std::endl;
  129. return 0;
  130. }

GitHubhttps://github.com/fengbingchun/Messy_Test

C++11中std::forward的使用 (转)的更多相关文章

  1. C++11中std::forward的使用

    std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...

  2. C++11中std::move、std::forward、左右值引用、移动构造函数的测试

    关于C++11新特性之std::move.std::forward.左右值引用网上资料已经很多了,我主要针对测试性能做一个测试,梳理一下这些逻辑,首先,左值比较熟悉,右值就是临时变量,意味着使用一次就 ...

  3. C++11中std::function的使用

    class template std::function is a general-purpose polymorphic function wrapper. Instances of std::fu ...

  4. C++11中std::move的使用

    std::move is used to indicate that an object t may be "moved from", i.e. allowing the effi ...

  5. C++11中std::bind的使用

    std::bind: Each argument may either be bound to a value or be a placeholder: (1).If bound to a value ...

  6. C++11中std::unordered_map的使用

    unordered map is an associative container that contains key-value pairs with unique keys. Search, in ...

  7. item 23: 理解std::move和std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 根据std::move和std::forward不 ...

  8. 用C++11的std::async代替线程的创建

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

  9. C++11 使用 std::async创建异步程序

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

随机推荐

  1. NOSQL之MONGODB

    MongoDB 基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案,它是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富, ...

  2. 一份11gR2 rac awr报告的简单分析

    昨晚网友发来一份awr报告,希望帮忙分析一下.由于其他信息都没有,仅仅只有一份awr,鉴于目前有大多的朋友还不太熟悉或者说不知道如何去进行awr的分析.我这里就拿这个awr来进行分析,当抛砖引玉了.首 ...

  3. ElementUI 知识点

    类型是number的el-input 去掉滚轮事件: @mousewheel.native.prevent <el-input type="number" @mousewhe ...

  4. windows 安装操作系统时切换分区表格式

    在出现分区管理界面时,按下shift+F10呼出命令行,输入diskpart 后尝试如下命令将磁盘分区表手动转换到MBR. list disk ---- 显示当前磁盘列表 select disk x ...

  5. linq to sql (Group By/Having/Count/Sum/Min/Max/Avg操作符) (转帖)

    http://wenku.baidu.com/link?url=2RsCun4Mum1SLbh-LHYZpTmGFMiEukrWAoJGKGpkiHKHeafJcx2y-HVttNMb1BqJpNdw ...

  6. 转jmeter --JDBC请求

    做JDBC请求,首先要了解这个JDBC对象是什么,然后寻找响应的数据库连接URL和数据库驱动. 数据库URL:jdbc:sqlserver://200.99.197.190:1433;database ...

  7. Ushare共享流媒体

    一. 支持USB 参考: http://wenku.baidu.com/link?url=K_uAp4QEa2cX3nPMkbc-colCAHA1yBwo1JCYsZf-qR7AVFPkmpbBVYR ...

  8. [C++ Primer] : 第13章: 拷贝控制

    拷贝, 赋值与销毁 当定义一个类时, 我们显示地或隐式地指定在此类型的对象拷贝, 移动, 赋值和销毁时做什么. 一个类通过定义5种特殊的成员函数来控制这些操作, 包括: 拷贝构造函数, 拷贝赋值运算符 ...

  9. 【jmeter】jmeter聚合报告之90%Line参数说明

    其实要说明这个参数的含义非常简单,可能你早就知道他的含义,但我对这个参数一直有误解,而且还一直以为是“真理”,原于一次面试,被问到了这个问题,所以引起我这个参数的重新认识. 先说说我错误的认识: 我一 ...

  10. file_get_contents failed to open stream: HTTP request failed(一个字符决定成败)

    file_get_contents 开始成功了.后来不知怎么的就报错,调试半天没发现什么问题. 结果.里面多了一个"空格"就报错.去掉空格就好了,你们仔细找找吧.