可变参数模板、右值引用带来的移动语义完美转发、lambda表达式的理解

可变参数模板

可变参数模板对参数进行了高度泛化,可以表示任意数目、任意类型的参数:
语法为:在class或者typename后面带上省略号。

Template<class ... T>
void func(T ... args)
{//
}

T:模板参数包,args叫做函数参数包
省略号作用:
1、声明一个包含0到任意个模板参数的参数包
2、在模板定义的右边,可以将参数包展开一个个独立的参数
c++11可以使用递归函数的方式展开参数包,获得可变参数的每个值。不过这个需要提供一个参数包展开函数和一个递归终止函数。
参数Args…在展开的过程中会递归调用自己,每调用一次,参数包中的参数就会少一个,直到所有参数都展开为止。

右值引用

1、临时对象的深拷贝

一个带有堆内存的类,必须提供一个深拷贝的拷贝函数。因为默认的拷贝构造函数是浅拷贝,会发生指针悬挂问题(两个对象的两个指针指向同一块内存,当函数作用结束后,两个对象分别调用析构函数,错误地将一块内存区析构两次)。
提供深拷贝地构造函数可以保证正确,但是会造成额外地性能损耗。
在这里插入图片描述
GetA函数会返回临时变量,然后通过这个临时变量拷贝构造一个新的对象a,临时变量在拷贝构造完成之后就销毁了。如果这个堆内存很大地话,拷贝构造的代价很大。也就是说每次产生临时变量都会造成额外地性能损失。

2、移动构造函数解决问题

A(A&& a) :m_ptr(a.m_ptr){a.m_ptr = nullptr;cout << "move construct" << endl;}

move construct这个构造函数是移动构造函数,它的参数是一个右值引用类型A&&。
它仅仅是将指针的所有者转移到了另一个对象上,同时将参数对象a的指针置空。也就是说,这里仅仅做了浅拷贝,从而避免了临时变量的深拷贝问题。

为什么能够匹配到这个构造函数呢?
这个构造函数只能够接受右值参数,而函数的返回值就是右值,所以就会匹配到这个构造函数。A&&看作临时值的标识。

对于临时值我们仅仅需要做浅拷贝即可,无需再做深拷贝,从而解决了临时变量拷贝构造产生的性能损失问题。这就是移动语义

3、左值借助移动语义优化性能

我们可以使用std::move将左值转换为右值引用。
move是将对象资源的所有权从一个对象转移到另一个对象,只是转移,没有内存的拷贝,这就是所谓的move语义。
通常这样使用:
使用move将左值转换成右值引用。应用移动语义,调用移动构造函数。
我们需要记住:
如果一个对象内部有较大的内存或者动态数组,就很有必要写move语义的拷贝构造函数和赋值函数,避免无所谓的深拷贝,以提高性能

左值引用和右值引用本质作用都是减少拷贝提高效率。
右值引用可以弥补左值引用不足的地方,右值引用做参数和做返回值减少拷贝的本质是利用了移动构造和移动赋值。
左值引用:
做参数: void func(T x) -> void func(T& x) 减少了传参过程中的拷贝
做返回值: T func() -> T& func() 减少返回过程中的宝贝(返回对象除了作用域不存在了就不能使用传引用了)
右值引用:
做参数: void func(T&& x) : 使func内部不再将x拷贝构造到容器空间上,而是采用移动构造
做返回值:利用移动构造减少拷贝。

4、完美转发

右值引用会在第二次之后的参数传递过程中右值属性丢失,在下一层调用中会识别成左值。
C++11引入完美转发的概念,完美转发是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数

#include<iostream>
using namespace std;
void Fun(int& x)
{cout << "左值引用" << endl;
}
void Fun(int&& x)
{cout << "右值引用" << endl;
}template<typename T>
void PerfectForward(T&& t) 
{Fun(std::forward<T>(t));
}int main()
{//右值引用PerfectForward(10);int a;//左值引用PerfectForward(a);//右值引用PerfectForward(std::move(a));return 0;
}

在这里插入图片描述

lambda表达式

lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量,定义如下:
[capture] (params)mutable->return_type{statement}

[capture] :捕获列表,捕获上下文变量以供lambda使用。编译器根据[]符号来判断接下来的代码是否是lambda函数。
(params):参数列表,与普通函数的参数列表一致,如果不需要传递参数,可以连同括号一起省略
mutable:修饰符,默认情况下lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略
return_type:返回值类型
{statement}:函数体,内容与普通函数一样,除了可以使用参数之外,还可以使用所捕获的变量。

lambda表达式与普通函数最大的不同就是它可以通过捕获列表访问一些上下文的数据。

[var] : 表示以 值传递方式 捕获 变量var
[=] : 表示以 值传递方式 捕获 所有父作用域的变量(包括this)
[&var] : 表示以 引用传递方式 捕获 变量var
[&] : 表示以 引用传递方式 捕获 所有父作用域的变量(包括this)
[this] : 表示以 值传递方式 捕获当前的this指针

lambda的类型被定义为“闭包”的类,通常用于stl库中。在某些场景下用于简化仿函数的使用,同时lambda作为局部函数,也会提高复杂代码的开发速度。可以在函数内部重用代码,不需要费心设计接口。
下面是示例代码:

#include<iostream>
using namespace std;int main()
{int a = 0, b = 1;//实现a+b的lambda表达式auto add1 = [](int x, int y)->int {return x + y;};cout << add1(a, b) << endl;auto add2 = [a, b]()->int {return a + b;};cout << add2() << endl;cout << a << " " << b << endl;//实现a和b的交换auto swap1 = [](int& x, int& y){int tmp = x;x = y;y = tmp;};swap1(a, b);cout << "swap1() " << a << " " << b << endl;auto swap2 = [&a, &b]()mutable{int tmp = a;a = b;b = tmp;};swap2();cout << "swap2() "<< a << " " << b << endl;return 0;
}

在这里插入图片描述

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

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

相关文章

BI-SqlServer

一.概述 SqlServer数据仓库ETL组件 IntegrationServiceOLAP组件 AnalysisService报表 ReportingServiceMDX(查多维数据集用的)和DMX(查挖掘模型用的)。二.商业智能-Analysis Services 项目 构建挖掘模型1构建挖掘模型2构建挖掘模型3三.商业智能-SqlServerAnalysis-Asp.net WebS…

python 子图大小_Python | 图的大小

python 子图大小In some cases, the automatic figure size generated by the matplotlib.pyplot is not visually good or there could be some non-acceptable ratio in the figure. So, rather than allowing a pyplot to decide the figure size, we can manually define t…

《设计模式整理》

目录常见设计模式如何保证单例模式只有一个实例单例模式中的懒汉与饿汉模式OOP设计模式的五项原则单例模式中的懒汉加载&#xff0c;如果并发访问该怎么做常见设计模式 单例模式&#xff1a; 单例模式主要解决了一个全局使用的类频繁的创建和销毁的问题。 单例模式下确保某一个…

JSON学习资料整理

1.什么是JSON JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript的一个子集。 JSON采用完全独立于语言的文本格式&#xff0c;但是也使用了类似于C语言家族的习惯&#xff08;包括C, C, C#, Java, JavaScript, Perl, Python等&#xff09;。这些…

OSI七层模型及其数据的封装和解封过程

OSI(Open System Interconnection)参考模型把网络分为七层: 1.物理层(Physical Layer) 物理层主要传输原始的比特流,集线器(Hub)是本层的典型设备; 2.数据链路层(Data Link Layer) 数据链路层负责在两个相邻节点间无差错的传送以帧为单位的数据,本层的典型设备是交换机(Switch)…

rss聚合模式案例_RSS的完整形式是什么?

rss聚合模式案例RSS&#xff1a;真正简单的联合 (RSS: Really Simple Syndication) RSS is an abbreviation of Really Simple Syndication. It is also called Rich Site Summary. It is quality attainment for the syndication of collection of web content and used to di…

《MySQL——38道查询练习(无连接查询)》

目录一、准备数据1、创建数据库2、创建学生表3、创建教师表4、创建课程表5、创建成绩表6、添加数据二、查询练习1、查询 student 表的所有行2、查询 student 表中的 name、sex 和 class 字段的所有行3、查询 teacher 表中不重复的 department 列4、查询 score 表中成绩在60-80之…

工作经常使用的SQL整理,实战篇(一)

工作经常使用的SQL整理&#xff0c;实战篇&#xff08;一&#xff09; 原文:工作经常使用的SQL整理&#xff0c;实战篇&#xff08;一&#xff09;工作经常使用的SQL整理&#xff0c;实战篇&#xff0c;地址一览&#xff1a; 工作经常使用的SQL整理&#xff0c;实战篇&#xff…

XPth和XSLT的一些简单用法

&#xff08;目的在于让大家知道有这个东西的存在&#xff09; XPath:即XML Path语言(Xpath)表达式使用路径表示法(像在URL中使用一样)来为XML文档的各部分寻址&#xff01; 关于XPath如何使用了&#xff0c;我们来看看&#xff01;当然这里面的代码只是入门&#xff0c;更深层…

isc dhcp_ISC的完整形式是什么?

isc dhcpISC&#xff1a;印度学校证书 (ISC: Indian School Certificate) ISC is an abbreviation of the Indian School Certificate. It alludes to the 12th class examination or higher secondary examination conducted by the Council for the Indian School Certificat…

《MySQL——连接查询》

内连接&#xff1a; inner join 或者 join 外连接 1、左连接 left join 或 left outer join 2、右连接 right join 或 right outer join 3、完全外连接 full join 或 full outer join 图示理解 全连接 创建person表和card表 CREATE DATABASE testJoin;CREATE TABLE person (…

win7下 apache2.2 +php5.4 环境搭建

这篇文章很好 没法复制 把链接粘贴来http://www.360doc.com/content/13/0506/13/11495619_283349585.shtml# 现在能复制了&#xff1a; 把任何一篇你要复制、却不让复制的文章收藏入收藏夹(直接CtrlD,确定) 2在收藏夹中&#xff0c;右击刚才收藏的那个网址&#xff0c;点属性 3…

HDU_1533 Going Home(最优匹配) 解题报告

转载请注明出自cxb:http://blog.csdn.net/cxb569262726 题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1533 说实话&#xff0c;这个题目刚开始还真看不出是完备匹配下的最大权匹配&#xff08;当然&#xff0c;这个也可以用网络流做。&#xff08;应该是添加…

c#中 uint_C#中的uint关键字

c#中 uintC&#xff03;uint关键字 (C# uint keyword) In C#, uint is a keyword which is used to declare a variable that can store an integral type of value (unsigned integer) the range of 0 to 4,294,967,295. uint keyword is an alias of System.UInt32. 在C&…

《MySQL——事务》

目录事务的必要性MySQL中如何控制事务手动开启事务事务的四大特征事务的四大特征事务开启方式事务手动提交与手动回滚事务的隔离性脏读现象不可重复读现象幻读现象串行化一些补充使用长事务的弊病commit work and chain的语法是做什么用的?怎么查询各个表中的长事务&#xff1…

运行在TQ2440开发板上以及X86平台上的linux内核编译

一、运行在TQ2440开发板上的linux内核编译 1、获取源码并解压 直接使用天嵌移植好的“linux-2.6.30.4_20100531.tar.bz2”源码包。 解压&#xff08;天嵌默认解压到/opt/EmbedSky/linux-2.6.30.4/中&#xff09; tar xvjf linux-2.6.30.4_20100531.tar.bz2 -C / 2、获取默认配置…

ArcCatalog ArcMap打不开

原来是因为&#xff1a; 连接了电信的无线网卡 关掉即可 启动ArcCatalog之后再开启无线网卡 没问题&#xff01;转载于:https://www.cnblogs.com/ccjcjc/archive/2012/08/21/2649867.html

Python熊猫– GroupBy

Python熊猫– GroupBy (Python Pandas – GroupBy) GroupBy method can be used to work on group rows of data together and call aggregate functions. It allows to group together rows based off of a column and perform an aggregate function on them. GroupBy方法可用…

MySQL索引底层原理理解以及常见问题总结

目录二叉查找树为索引红黑树为索引B树作为索引B树作为索引MyISAM存储引擎索引实现InnoDB存储引擎索引实现常见问题聚集索引与非聚集索引InnoDB基于主键索引和普通索引的查询有什么区别&#xff1f;InnoDB主键索引为何是整型的自增主键何时使用业务字段作为主键呢&#xff1f;哈…

Spring之HibernateTemplate 和HibernateDaoSupport

spring提供访问数据库的有三种方式&#xff1a; HibernateDaoSupport HibernateTemplate&#xff08;推荐使用&#xff09; jdbcTemplate(我们一般不用&#xff09; 类所在包&#xff1a; HibernateTemplate&#xff1a;org.springframework.orm.hibernate3.HibernateTemplate …