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;
}

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. 开始学习git

    今天看着廖雪峰的git使用教程开始学习git.不过没有将项目托管在github上,而是选择托管在了码云上. 看着明白做起来还是出了些问题,不过好在最后都解决了.果然眼高手低要不得. 试着将自己平时学习 ...

  2. 【转载】#458 Errors While Converting Between enum and Underlying Type

    You can convert to an enum value from its underlying type by casting the underlying type (e.g. int) ...

  3. fiddler和charles

    (4)学习浏览器代理和手机网络抓包,涉及到了fiddler和charles,

  4. 从零开始Vue项目实战(二)-搭建环境

    1.下载node.js并安装 下载地址:https://nodejs.org/en/download/. 下载.msi 格式的直接连续下一步就可以了.安装完成后可以用 node -v 和 npm -v ...

  5. 剑指offer23 从上往下打印二叉树

    没有把队列的头部弹出,出现内存错误:

  6. idea原生ajax数据处理(增删改查)

    项目名称:Bookstore UI界面 项目文件 操作: jsp代码 <%@ page import="dao.BookDAO" %> <%@ page impo ...

  7. 【洛谷P2447】[SDOI2010]外星千足虫

    外星千足虫 题目链接 首先,它一看题解就是个高斯消元 只是改成了奇偶性的判断 性质: 奇数+奇数=偶数 奇数+偶数=奇数 偶数+奇数=奇数 偶数+偶数=偶数 于是我们用1表示奇数,0表示偶数 1+1= ...

  8. 【luogu P3379 最近公共祖先】 模板

    题目链接:https://www.luogu.org/problemnew/show/P3379 倍增求lca,先存下板子,留个坑以后再填讲解. in 5 5 43 12 45 11 42 43 23 ...

  9. <body> 中的 JavaScript 函数

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  10. JS JavaScript中的this

    this是JavaScript语言中的一个关键字 它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用. function test() { this.x = 1; } 上面代码中,函 ...