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(); 但是线程毕竟是属于比 ...
随机推荐
- arcgis desktop can not connect to previous version of license manager
解决方法: license manager以 管理员身份运行.
- ORACLE11g 安装中xhost: unable to open display 问题解决纪实 (go)
http://blog.csdn.net/mchdba/article/details/62235761 1,Xhosts报错 安装好vncserver,本地pc笔记本能通过vnc viewer远程连 ...
- React-Native 在android写不支持gif的解决方案!
只需要在android/app/build.gradle中的dependencies字段中添加: compile 'com.facebook.fresco:animated-gif:0.13.0' 然 ...
- Hadoop通过路径和和链接访问HDFS
如果既想在Hadoop服务器本地可以通过绝对路径如"/user/hadoop"方式访问hdfs,也想通过"hdfs://local host:9000/user/hado ...
- Zabbix二次开发_02获取数据
最近准备写一个zabbix二次页面的呈现.打算调用zabbix api接口来进行展示. 具体流程以及获取的数据. 1. 获得认证密钥 2. 获取zabbix所有的主机组 3. 获取单 ...
- windows下Nginx反向代理服务器安装与配置
感谢慕课网Geely老师的讲解,本人将Nginx进行如下的总结. Nginx是一款轻量级的Web服务器,也是一款反向代理服务器,其主要特点:高稳定, 高性能,资源占用少功能丰富,模块化结构 支持热部署 ...
- 小峰servlet/jsp(6)jstl核心标签库
一.引入jstl 需要jstl.jar;standard.jar; 二.jstl核心标签库: c:out 内容输出标签; c:set 用来设置4种属性范围值的标签: c:re ...
- Mybatis学习(1)
一.原生态jdbc程序存在的问题: mybatis框架原理.执行过程: 二.入门程序 完成入门程序的以下需求: 1.根据用户id(主键)查询用户信息: 2.根据用户名称模糊查询用户信息: 3.添加用户 ...
- Fix-Dell iDRAC 7 error: RAC0218: The maximum number of user sessions is reached
Hi Everyone, We came across the following error while performing some preventative maintenance check ...
- [UE4]代理事件(C++)
用宏定义类似格式: DECLARE_DELEGATE //普通代理 DECLARE_DYNAMIC_DELEGATE_TwoParams //动态代理 DECLARE_DYNAMIC_MULTICAS ...