C++11中std::forward的使用
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:
#include "forward.hpp" #include <utility> #include <iostream> #include <memory> #include <string> ////////////////////////////////////////////// // reference: http://en.cppreference.com/w/cpp/utility/forward struct A { A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; } A(int& n) { std::cout << "lvalue overload, n=" << n << "\n"; } }; class B { public: template<class T1, class T2, class T3> B(T1&& t1, T2&& t2, T3&& t3) : a1_{ std::forward<T1>(t1) }, a2_{ std::forward<T2>(t2) }, a3_{ std::forward<T3>(t3) } { } private: A a1_, a2_, a3_; }; template<class T, class U> std::unique_ptr<T> make_unique1(U&& u) { return std::unique_ptr<T>(new T(std::forward<U>(u))); } template<class T, class... U> std::unique_ptr<T> make_unique(U&&... u) { return std::unique_ptr<T>(new T(std::forward<U>(u)...)); } int test_forward1() { auto p1 = make_unique1<A>(2); // rvalue int i = 1; auto p2 = make_unique1<A>(i); // lvalue std::cout << "B\n"; auto t = make_unique<B>(2, i, 3); return 0; } //////////////////////////////////////////////////////// // reference: http://www.cplusplus.com/reference/utility/forward/ // function with lvalue and rvalue reference overloads: void overloaded(const int& x) { std::cout << "[lvalue]"; } void overloaded(int&& x) { std::cout << "[rvalue]"; } // function template taking rvalue reference to deduced type: template <class T> void fn(T&& x) { overloaded(x); // always an lvalue overloaded(std::forward<T>(x)); // rvalue if argument is rvalue } int test_forward2() { int a; std::cout << "calling fn with lvalue: "; fn(a); std::cout << '\n'; std::cout << "calling fn with rvalue: "; fn(0); std::cout << '\n'; return 0; } ////////////////////////////////////////////////////// // reference: http://stackoverflow.com/questions/8526598/how-does-stdforward-work template<class T> struct some_struct{ T _v; template<class U> some_struct(U&& v) : _v(static_cast<U&&>(v)) {} // perfect forwarding here // std::forward is just syntactic sugar for this }; int test_forward3() { /* remember the reference collapsing rules(引用折叠规则): 前者代表接受类型,后者代表进入类型,=>表示引用折叠之后的类型,即最后被推导决断的类型 TR R T& &->T& // lvalue reference to cv TR -> lvalue reference to T T& &&->T& // rvalue reference to cv TR -> TR (lvalue reference to T) T&& &->T& // lvalue reference to cv TR -> lvalue reference to T T&& &&->T&& // rvalue reference to cv TR -> TR (rvalue reference to T) */ some_struct<int> s1(5); // in ctor: '5' is rvalue (int&&), so 'U' is deduced as 'int', giving 'int&&' // ctor after deduction: 'some_struct(int&& v)' ('U' == 'int') // with rvalue reference 'v' bound to rvalue '5' // now we 'static_cast' 'v' to 'U&&', giving 'static_cast<int&&>(v)' // this just turns 'v' back into an rvalue // (named rvalue references, 'v' in this case, are lvalues) // huzzah, we forwarded an rvalue to the constructor of '_v'! // attention, real magic happens here int i = 5; some_struct<int> s2(i); // in ctor: 'i' is an lvalue ('int&'), so 'U' is deduced as 'int&', giving 'int& &&' // applying the reference collapsing rules yields 'int&' (& + && -> &) // ctor after deduction and collapsing: 'some_struct(int& v)' ('U' == 'int&') // with lvalue reference 'v' bound to lvalue 'i' // now we 'static_cast' 'v' to 'U&&', giving 'static_cast<int& &&>(v)' // after collapsing rules: 'static_cast<int&>(v)' // this is a no-op, 'v' is already 'int&' // huzzah, we forwarded an lvalue to the constructor of '_v'! return 0; } //////////////////////////////////////////////////// // reference: https://oopscenities.net/2014/02/01/c11-perfect-forwarding/ void sum(int a, int b) { std::cout << a + b << std::endl; } void concat(const std::string& a, const std::string& b) { std::cout<< a + b << std::endl; } void successor(int a, int& b) { b = ++a; } template <typename PROC, typename A, typename B> void invoke(PROC p, A&& a, B&& b) { p(std::forward<A>(a), std::forward<B>(b)); } int test_forward4() { invoke(sum, 10, 20); invoke(concat, "Hello", "world"); int s = 0; invoke(successor, 10, s); std::cout << s << std::endl; return 0; }
GitHub:https://github.com/fengbingchun/Messy_Test
C++11中std::forward的使用的更多相关文章
- C++11中std::forward的使用 (转)
std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...
- C++11中std::move、std::forward、左右值引用、移动构造函数的测试
关于C++11新特性之std::move.std::forward.左右值引用网上资料已经很多了,我主要针对测试性能做一个测试,梳理一下这些逻辑,首先,左值比较熟悉,右值就是临时变量,意味着使用一次就 ...
- C++11中std::function的使用
class template std::function is a general-purpose polymorphic function wrapper. Instances of std::fu ...
- C++11中std::move的使用
std::move is used to indicate that an object t may be "moved from", i.e. allowing the effi ...
- 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 ...
- C++11中std::unordered_map的使用
unordered map is an associative container that contains key-value pairs with unique keys. Search, in ...
- item 23: 理解std::move和std::forward
本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 根据std::move和std::forward不 ...
- 用C++11的std::async代替线程的创建
c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...
- C++11 使用 std::async创建异步程序
c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...
随机推荐
- HTTPS科普(转)
为什么需要https HTTP是明文传输的,也就意味着,介于发送端.接收端中间的任意节点都可以知道你们传输的内容是什么.这些节点可能是路由器.代理等. 举个最常见的例子,用户登陆.用户输入账号,密码, ...
- OAuth 2.0协议在SAP产品中的应用
阮一峰老师曾经在他的博文理解OAuth 2.0里对这个概念有了深入浅出的阐述. http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 本文会结合我 ...
- fastcgi+lighttpd+c语言 实现搜索输入提示
1.lighttpd 服务器 lighttpd是一个比较轻量的服务器,在运行fastcgi上效率较高.lighttpd只负责投递请求到fastcgi. centos输入yum install ligh ...
- OC block声明和使用
#import "Button.h" typedef int (^MySum) (int, int); void test() { // 定义了一个block,这个block返回值 ...
- 03_P52 课后作业
1. 软件开发的早期阶段为什么进行可行性研究?应该从哪些方面研究系统的可行性? 1.进行可行性研究是为了该软件项目是否值得开发?是否具有经济效益?是否违反法律道德?是否技术可以实现?是否风险性高? 2 ...
- POJ 3088 斯特林
题意:有一个n个按钮的锁,按下一些按钮打开门,有多少开门方式,其中,一些按钮可以选,可以不选,选中的按钮 可以分成一些集合,集合之间无序,是同时按下的. 分析: 1.首先选择 i 个按钮,组合数 2. ...
- 【[APIO2012]派遣】
题目 直接线段树合并就好了 之后在线段树上二分贪心选取金额较少的 如果是左偏树的话就开一个大根堆,根和子树顺次合并,合并之后堆内所有元素总和如果大于\(m\)就删除堆顶,由于每个元素只会被删除一次,所 ...
- c#主窗体以及副窗体弹出
在program.cs中,Form1的位置就是主窗体的位置(主窗体特征:关闭窗体应用程序结束) 弹出副窗口(点击按钮弹出窗口) Close为关闭窗口(关闭对应对象,需要先自己new一个) this.C ...
- 不能安装这个“安装 OS X EI Capitan”应用程序副本不能验证” 的解决办法
不能安装这个“安装 OS X EI Capitan”应用程序副本不能验证.它在下载过程中可能已遭破坏或篡改. 解决办法:修改系统时间. 1,查看你的dmg文件的创建日期 2,把你的系统日期修改到比这个 ...
- c语言描述的静态查找表
顺序表的查找: 直接循环依次和目标比较就行 有序表的查找(二分查找): int search(SS *T,Type key){ int mid; ; int high=T.length; while( ...