c++ forward关键字

forward的由来:模板函数中的推导类型,作为另一函数的参数时,不管实参是什么类型,作为另一个参数的实参时,都变成了左值。因为C++里规定函数的形参就是左值,不过调用侧的实参是否是右值。所以,调用的另一个函数的形参即使用T&& arg来声明,传过去的也是左值,编译不过,因为不能自动把左值转化成右值,除非使用std::move。forward就是为了解决这个问题的。

forward() 函数的作用:保持住实参的类型。
include <iostream>
using namespace std; void rvalue_call(int& v){
cout << "& call" << endl;
}
void rvalue_call(int&& v){
cout << "&& call" << endl;
}
void rvalue_call(const int& v){
cout << "const & call" << endl;
}
void rvalue_call(const int&& v){
cout << "const && call" << endl;
} template<typename T>
void func(T&& a){
rvalue_call(a);
} int main(void){
int x = 1;
func(x);//实参为左值
int& y = x;
func(y);//实参为左值引用
func(std::move(y));//实参为右值引用
func(100);//实参为右值引用
const int a = 11;
func(a);//实参为左值常引用
func(std::move(a));//实参为右值常引用
}

执行结果:

& call
& call
& call
& call
const & call
const & call

上面的例子即使传递的是右值,但也不能够调用到

void rvalue_call(int&& v)
void rvalue_call(const int&& v)

解决办法:加std::forward

#include <iostream>
using namespace std; void rvalue_call(int& v){
cout << "& call" << endl;
}
void rvalue_call(int&& v){
cout << "&& call" << endl;
}
void rvalue_call(const int& v){
cout << "const & call" << endl;
}
void rvalue_call(const int&& v){
cout << "const && call" << endl;
} template<typename T>
void func(T&& a){
rvalue_call(std::forward<T> (a));
} int main(void){
int x = 1;
func(x);//实参为左值
int& y = x;
func(y);//实参为左值引用
func(std::move(y));//实参为右值引用
func(100); const int a = 11;
func(a);
func(std::move(a));
}

执行结果:发现可以调用到右值的两个函数。这就是std::forward函数在模板里的作用

& call
& call
&& call
&& call
const & call
const && call

另一个例子:

#include <iostream>
#include <utility> template<typename F, typename T1, typename T2>
void fcn2(F f, T1&& t1, T2&& t2){
f(std::forward<T2>(t2), std::forward<T1>(t1));//OK
//f(std::move(t2), std::forward<T1>(t1));//OK
//f(t2, t1);//ERROR
} void f1(int&& i1, int& i2){
i1 = 10;
i2 = 20;
} int main(){
int i1 = 1, i2 = 2;
int& a = i1;
int& b = i2;
int&& c = 111; fcn2(f1, i1, 42);//因为42为右值,所以fcn2的T2为右值,如果不加forward,把T2的形参传给另一个函数时,它就变成了左值,但是函数f1的参数时右值,这时,编译就不过了。
std::cout << i1 << ", " << i2 << std::endl; }

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

c/c++ 右值引用,forward关键字的更多相关文章

  1. c++ 右值引用,move关键字

    c++ move关键字 move的由来:在 c++11 以前存在一个有趣的现象:T&  指向 lvalue (左传引用), const T& 既可以指向 lvalue 也可以指向 rv ...

  2. Item 25: 对右值引用使用std::move,对universal引用则使用std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 右值引用只能绑定那些有资格被move的对象上去.如 ...

  3. 第16课 右值引用(3)_std::forward与完美转发

    1. std::forward原型 template <typename T> T&& forward(typename std::remove_reference< ...

  4. C++11新特性之右值引用(&&)、移动语义(move)、完美转换(forward)

    1. 右值引用 个人认为右值引用的目的主要是为了是减少内存拷贝,优化性能. 比如下面的代码: String Fun() { String str = "hello world"; ...

  5. 透彻理解C++11新特性:右值引用、std::move、std::forward

    目录 浅拷贝.深拷贝 左值.右值 右值引用类型 强转右值 std::move 重新审视右值引用 右值引用类型和右值的关系 函数参数传递 函数返还值传递 万能引用 引用折叠 完美转发 std::forw ...

  6. C++ 右值引用与 const 关键字

    C++11 新增了另一种引用:右值引用(rvalue reference),这种引用可指向右值,是使用 && 声明的.使用右值引用可以减少复制操作,延长临时对象生命周期,提升程序性能. ...

  7. [转载] C++11中的右值引用

    C++11中的右值引用 May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移动语义std::move() 右值引用和右值的关系 完美转发 引用折叠推导 ...

  8. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part8:Perfect Forwarding(完美转发):解决方案

    本文为第八部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...

  9. C++11中的右值引用

    原文出处:http://kuring.me/post/cpp11_right_reference May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移 ...

随机推荐

  1. Android之Retrofit详解(转载)

    说明:该文章转载于https://www.jianshu.com/p/a3e162261ab6 前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下 ...

  2. 6.[leetcode] ZigZag Conversion

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  3. @SuppressWarnings("rawtypes") 是什么含义

    简介:java.lang.SuppressWarnings是J2SE 5.0中标准的Annotation之一.可以标注在类.字段.方法.参数.构造方法,以及局部变量上.作用:告诉编译器忽略指定的警告, ...

  4. 一些关于StringAPI的题目

    一:知识点 1.字符串"你好北京"中每个字符占用2个内存字节数.字符串底层由字符数组构成,每个字符占用内存2个字节. 2.重写toString 一般对象都有这个方法,目的是将对象按 ...

  5. Linux配置成网关

    之前按照诸葛建伟的metasploit魔鬼训练营搭了个简单的内网环境,其中就是一台linux作为内网网关.但是虚拟机开启的时候经常出现包不能转发的情况,也就是网关没有配置好. 在网上找了好几个才找到适 ...

  6. .NET Core微服务之基于Steeltoe使用Eureka实现服务注册与发现

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 =>  Steeltoe目录快速导航: 1. 基于Steeltoe使用Spring Cloud Eureka 2. 基于Steelt ...

  7. 【反编译系列】二、反编译代码(jeb)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 一般情况下我们都是使用dex2jar + jd-gui的方式反编译代码,在实际使用过程中,有时候发现反编译出来的代码阅读效果不是很好 ...

  8. Kubernetes的DaemonSet(上篇)

    背景 静儿作为美团容器化团队HULK的一员,经常需要和Kubernetes(k8s)打交道.第一次登陆node(宿主机)的时候,发现连续登陆几台都看到了Prometheus-Node-Exporter ...

  9. springcloud~Eureka实例搭建

    服务端 build.gradle配置 dependencies { compile('org.springframework.cloud:spring-cloud-starter-netflix-eu ...

  10. Ubuntu下搜狗输入法的安装教程

            前面写过一篇centos7下搜狗输入法的安装教程,现在把搜狗输入法在Ubuntu下的安装方法也记录一下,相比之下Ubuntu下安装搜狗输入法要简便得多 安装fcitx以支持搜狗输入法 ...