C++ std::move()和完美转发

std::move()、std::forward<T>、模板类型推断分析

 

引用折叠原则和完美转发是有联系的,可以说后者是基于前者的某些特性实现的,具体来看一下。

要理解完美转发,需要了解两个知识点:

  1. 引用折叠原则(Reference collapsing rules)。

  2. 右值函数模版参数类型推导(Template argument deduction)

我们先来分析一下为什么需要使用到move呢?

C++11多出来一个move语义,意图是解决临时对象重复拷贝和释放引发的资源浪费,move与右值引用进行搭配可以完美的解决这个问题。
比如在进行vector中的insert函数的时候,如果模板类型是string,通过move(str1)我们就可以只将string中的指针进行交换,即可实现插入到vector容器中的操作。而不用再进行深拷贝的动作。
需要注意的是,如果使用move进行左值变右值之后,该左值不能再利用,因为它里面的信息可能已经被更改,对应的string就是,指向字符串的指针被打断了。

下面这张图是模板类型推断原则:

 
这是函数模板参数类型推导中一种比较特殊的情况,这种情况会把模板参数作为右值引用使用,例如:

template<typename T>  
void foo(T&&);  
  •  

其中T为模板类型,T&&为参数类型。这种情况会产生两种结果:

1. 当传给foo函数的参数是一个左值引用时,例如:

int i = 29;  
foo(i);//i为左值引用  
  •  

此时,T的类型为int的左值引用:int&,参数类型为int & &&,(既T&&),结合上面的引用折叠规则,最终参数的类型为int的左值引用:int&。
2. 当传给foo函数的参数是一个右值引用时,例如:

foo(29);
  •  

此时,T的类型为int,参数类型为int&&,(既T&&)。

那么,为什么需要forward呢?
我们先来看下以下例子:

template<typename T>
void show1(T && a)
{cout << "我是右值引用" << endl;
}template<typename T>
void show1(T & a)
{cout << "我是左值引用" << endl;
}template<typename T>
void show(T && a)
{show1(forward<T>(a));
}
//我们通过以下进行调用;
show(2);
  •  

该函数第进入show之后会调用show1的调用,如果此时没有用forward进行转发的话,会调用到
左值引用版本,而不会调用到右值引用的版本。所有forward就是进行完美转发的作用,当传入的是左值引用
的时候,会调用到左值引用的版本,当调用到右值引用的时候,函数里面也会调用到右值引用的版本 那么他是怎么实现的呢?
通过以上代码的分析,我们可以发现,forward会进行类型的转发。具体实现原理就是上面所说的引用折叠原则。

下面是VS2015下的实现源码。

// TEMPLATE FUNCTION forward
template<class _Ty> inlineconstexpr _Ty&& forward(typename remove_reference<_Ty>::type& _Arg) _NOEXCEPT{	// forward an lvalue as either an lvalue or an rvaluereturn (static_cast<_Ty&&>(_Arg));}template<class _Ty> inlineconstexpr _Ty&& forward(typename remove_reference<_Ty>::type&& _Arg) _NOEXCEPT{	// forward an rvalue as an rvaluestatic_assert(!is_lvalue_reference<_Ty>::value, "bad forward call");return (static_cast<_Ty&&>(_Arg));}

我们就上面那个例子来进行分析:
1、传入的是左值的时候。

void show(int&   && a)
{//此时T为 int&类型。a通过引用折叠原则为int&类型show1(forward<int&>(a));
}

此时forward会调用下面这个版本的函数。

	constexpr int& && forward(typename remove_reference<int&>::type& _Arg) _NOEXCEPT{	// forward an lvalue as either an lvalue or an rvaluereturn (static_cast<int& &&>(_Arg));}

那么,此时返回的就是int& &&类型,通过引用折叠原则即为 int &,完成了左值的转发

2、传入的是右值的时候。

下面是类型推断调用的时候生成的函数。

void show(int && a)
{//此时T为 int类型。a为 int&& 类型show1(forward<int>(a));
}
  •  

相应地就会调用到下面这个forward版本:

constexpr int && forward(typename remove_reference<int>::type&& _Arg) _NOEXCEPT
{	// forward an rvalue as an rvalue
static_assert(!is_lvalue_reference<int>::value, "bad forward call");
return (static_cast<int &&>(_Arg));
}

我们可以看出上面的这个forward会返回右值引用,则实现了右值引用的完美转发。

总结

1、move函数是将一个左值转为右值引用,转换之后,改左值就不能再进行使用了。
2、forward函数是进行类型的转发,可以将左值引用继续转发为左值,右值引用继续转发为右值引用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线面要素类相互转换-原创

一、线转面的步骤 1、线几何属性转面几何属性ArcToolbox-Data Management Tools-Features-Feature To polygon&#xff0c;此过程只是将几何属性做了转换&#xff0c;得到的是属性信息丢失了的面t_L_HDBX_FeatureToPolygon1 2、 在ArcMap中将t_L_HDBX_FeatureToPolygon1全选&a…

SEO网站标题怎么优化

经过前两天发的两篇原创文章被加精之后&#xff0c;我的热情是一发不可收拾&#xff0c;忍不住又想写点干货给大家分享&#xff01;今天分析一下网站标题如何设置之SEO技巧。通过标题就可以看出&#xff0c;今天是讲网站标题如何设置&#xff0c;为什么要写这个呢&#xff1f;因…

Redis淘汰删除策略

Redis淘汰删除策略Redis淘汰删除策略6种淘汰Key策略3种删除过期键策略定时删除惰性删除定期删除其他模块的淘汰处理RDB 快照持久化创建载入AOF 只追加持久化写入重写主从复模式下对过期键的处理6种淘汰Key策略Redis中通过maxmemory参数来设定内存的使用上限&#xff0c;当Redis…

MySQL NDB Cluster

1. MySQL Cluster 是一种技术&#xff0c;该技术允许在无共享的系统中部署“内存中”数据库的 Cluster 。通过无共享体系结构&#xff0c;系统能够使用廉价的硬件&#xff0c;而且对软硬件无特殊要求。此外&#xff0c;由于每个组件有自己的内存和磁盘&#xff0c;不存在单点故…

《上邪》诗解

上邪&#xff01;①   我欲与君相知②&#xff0c; 长命③无绝衰。   山无陵④&#xff0c; 江水为竭&#xff0c;   冬雷震震⑤&#xff0c; 夏雨雪⑥ &#xff0c;   天地合⑦ &#xff0c; 乃敢⑧与君绝&#xff01;天啊&#xff01;我愿与你相爱&#xff0c;让我们…

win8 关于Adobe CS6系列软件Patch覆盖失败的问题(Photoshop CS6、Adobe Illustrator CS6、Adobe Fireworks CS6)...

我在Adobe文件夹下安装了Photoshop CS6和 Adobe Illustrator CS6&#xff0c;结果当我为AI覆盖Path文件后&#xff0c;我发现PS和AI全部都打不开了。反复覆盖还是没用。 不过很奇怪fireworks Cs6能用。FW我没有跟PS、AI装在同一个文件夹下。 我想难道是安装目录的问题&#xff…

获取Spring容器管理的Bean工具类

很多时候我们在一些不受spring管理的类中需要用到spring管理的Bean&#xff0c;那么这个时候可以使用如下工具类从spring容器中获取相关的Bean实例。 Component public class SpringApplicationContextUtils implements ApplicationContextAware {private static final Logger …

mysql - 内存表使用总结

部分转载&#xff1a;https://blog.csdn.net/hemeinvyiqiluoben/article/details/51222951?utm_mediumdistribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&dist_request_id&depth_1-utm_sourcedistribute.…

《集体智慧编程》——第一章导读

为什么80%的码农都做不了架构师&#xff1f;>>> 什么是集体智慧 其含义是指&#xff1a;为了长早新的想法&#xff0c;而将一群人的行为、偏好或思想组合在一起。 完成这项工作的一种最为基础的方法&#xff0c;便是使用调查问卷或普查。从一大群人中搜集的答案可…

使用spring的@autowired注解,无法实例化dao

首先理解spring的注解注入dao接口的目的是什么&#xff0c;是为了接口不用进行实例化就可以被任何一个类去调用 我昨天下午就是发现&#xff0c;不同的类&#xff0c;一模一样的注解&#xff0c;为什么前面的类可以使用注解调用mapper的sql查询&#xff0c;但是 第二个类死活无…

大括号之谜:C++的列表初始化语法解析

转载&#xff1a; https://segmentfault.com/a/1190000039362151 摘要&#xff1a;有朋友在使用std::array时发现一个奇怪的问题&#xff1a;当元素类型是复合类型时&#xff0c;编译通不过。 有朋友在使用std::array时发现一个奇怪的问题&#xff1a;当元素类型是复合类型时&a…

在Mono 2.8上部署ASP.NET MVC 2

Mono 2.8发布&#xff1a;C#4.0和更好的性能&#xff0c;我们知道Mono 2.8对ASP.NET MVC 2的完全支持&#xff0c;下面我们就来测试下在Mono 2.8上部署ASP.NET MVC 2应用程序。我的环境是Opensuse 11.3,通过以下命令部署好Mono 2.8的开发环境&#xff0c;之所以说是开发环境是同…

ASP.NET C# 数字格式化输出

int a 12345678; //格式为sring输出 Label1.Text string.Format("asdfadsf{0}adsfasdf",a); Label2.Text "asdfadsf"a.ToString()"adsfasdf"; Label1.Text string.Format("asdfadsf{0:C}adsfasdf",a);//asdfadsf&#xffe5;1,234…

gdb调试时,Program received signal SIGPIPE, Broken pipe.

今天在gdb调试时&#xff0c;发现总是出现Program received signal SIGPIPE, Broken pipe&#xff0c;搜索了网上的资料&#xff0c;发现是在调试时&#xff0c;接收到了SIGPIPE这个signal信号导致调试被中断。 By default, gdb captures SIGPIPE of a process and pauses it.…

看到一个暴强的翻译,闲的蛋疼,写个c#版的

在豆瓣上看到一篇关于拿破仑的翻译&#xff0c;文科生的翻译有几段相当传神&#xff0c;不得不佩服汉语的强大。有好事者还用程序语言实现了一下&#xff0c;现已有java、python和html的版本&#xff0c;我也来写个渺小的C#版本&#xff0c;运行结果和java版是一致的&#xff0…

太多的想法,反而不是什么好兆头

太多的想法&#xff0c;反而不是什么好兆头&#xff0c;思绪太多&#xff0c;反而影响专心做另外一件事情&#xff01;转载于:https://blog.51cto.com/newsnews/1113359

电销会员分销

AI(人工智能)机器人:真人语音智能流畅对话&#xff0c;支持打断&#xff0c;自动录音。自动按意向分A B C D 类。代替电销人员打电话&#xff0c;减少80%的重复劳动!低成本,高效率。 web部分&#xff0c;对接机器人&#xff0c;机器人智能语言交互。对一些做电销的企业来讲节省…

raft协议中统计一条log被多少节点复制

在raft协议中&#xff0c;client的请求都会转化为一条log&#xff0c;并且只能由leader才能处理来自client的请求&#xff0c;如果一个log请求到了follower上&#xff0c;最后也会重定向到leader上的。 好的&#xff0c;废话说多了&#xff0c;开始主题&#xff1a;raft协议中…

[笔记][原创]Verilog HDL语法分析笔记

这篇帖子用于记录学习Verilog过程中的一些syntax的问题&#xff0c;会不断更新&#xff0c;有不正确的地方请各位帮忙指正:D一.Verilog 语法中的可综合性Verilog HDL 真的很强大&#xff0c;如果程序只用于仿真&#xff0c;那么几乎所有的语法和编程语句都可以使用。但如果程序…

SRV记录注册不成功的可能的原因

1.1.1 SRV记录注册不成功的可能的原因 默认情况&#xff0c;安装完活动目录就会DNS中的SRV记录就注册成功了&#xff0c;如果您在域控制器上重启Netlogon服务&#xff0c;有可能还是不能注册SRV记录到DNS服务器上&#xff0c;以下是总结的需要检查的几点。 DNS区域名字是否正确…