C++11中std::forward的使用
来源:互联网 发布:求数组平均值 编辑:程序博客网 时间:2024/05/16 12:46
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/forwardstruct 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); // rvalueint i = 1;auto p2 = make_unique1<A>(i); // lvaluestd::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 lvalueoverloaded(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-worktemplate<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 RT& &->T& // lvalue reference to cv TR -> lvalue reference to TT& &&->T& // rvalue reference to cv TR -> TR (lvalue reference to T)T&& &->T& // lvalue reference to cv TR -> lvalue reference to TT&& &&->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 hereint 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++/C++11中std::transform的使用
- C++/C++11中std::queue的使用
- C++/C++11中std::priority_queue的使用
- C++/C++11中std::deque的使用
- C++/C++11中std::stack的使用
- C++/C++11中std::numeric_limits的使用
- C++/C++11中std::exception的使用
- C++/C++11中std::runtime_error的使用
- C++11: std::forward
- [C/C++]关于C++11中的std::move和std::forward
- [C/C++]关于C++11中的std::move和std::forward
- [C/C++]关于C++11中的std::move和std::forward
- C++11 std::move和std::forward
- C++11:std::move和std::forward
- C++11中移动语义(std::move)和完美转发(std::forward)
- C++11中std::unordered_map的使用
- C++11中std::move的使用
- DirectX学习笔记(十):3D字体的实现及用ID3DXFont接口绘制文本
- (iOS逆向工程)class-dump 安装与使用
- FarManager3 打开界面混乱问题
- 139. Word Break
- android判断网络连接状态
- C++11中std::forward的使用
- golang 调用cmd下程序隐藏黑窗口-方法1
- 高精度大数加法
- HDU5901大素数模板
- android -调用系统相机录像
- Vue.js实现表格渲染
- 第四周项目5--多项式求和
- 1020 月饼
- 【机器学习】机器学习泛泛之谈