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的使用的更多相关文章

  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. CRM中间件里的发布-订阅者模式

    从事务码SMW01里能观察到一个BDOC可能被发送往不止一个目的site去,比如下图所示的5个site都会收到该site,而高亮显示的SMOF_ERPSITE代表ERP系统QI3的client 504 ...

  2. Android(java)学习笔记10:同步中的死锁问题以及线程通信问题

    1. 同步弊端: (1)效率低 (2)如果出现了同步嵌套,就容易产生死锁问题 死锁问题及其代码 : (1)是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象 (2)同步代码块的 ...

  3. 【[SDOi2012]Longge的问题】

    求\(\sum_{i=1}^ngcd(i,n)\) 考虑枚举\(gcd\),现在答案变成这样 \(\sum_{d|n}d*f(d)\) \(f(d)=\sum_{i=1}^n [gcd(i,n)==d ...

  4. 2016 ACM/ICPC亚洲区大连站-重现赛 解题报告

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=5979 按AC顺序: I - Convex Time limit    1000 ms Memory li ...

  5. Zookeep启动异常:Error contacting service. It is probably not running.

    异常提示: [root@hadoop bin]# ./zkServer.sh status JMX enabled by default Using config: /usr/local/zk/bin ...

  6. Tomcat+Oracle配置连接池的例子

    我这有一个Tomcat+Oracle连接池的例子,放上来和大家分享一下. Tomcat +Oracle  连接池配置   Author: Kenneth.Leaf@GalaxySoft Date: / ...

  7. 使用transfor让图片旋转

    材料:Transform,onmouseout,onmouseover css: html: js:

  8. Python 学习笔记(八)Python列表(三)

    序列 序列:数学上,序列是被排成一列的对象(或事件):这样,每个元素不是在器他元素之前,就是在其他元素之后.这里元素之间的顺序非常重要.<维基百科> 序列是Python中最基本的数据结构. ...

  9. 使用unity3D生成项目(Easy Movie Texture)运行出现的问题

    运行后,首先报的错需要改  -fno-objc-arc 编译后出现的新的错.   需要将   CustomVideoPlayer.mm _lastFrameTimestamp = _curFrameT ...

  10. python2.7打包环境配置

    目前python3.x正大行其道,不过有些公司依然使用python2.x,比如说我现在的公司.网上python2.x解决方案还是有些空缺,需要自己去查找. 公司的电脑安装的python2.7,pip也 ...