「C++」C++11新特性

news2025/2/28 5:13:36
在这里插入图片描述

💻文章目录

  • 📄前言
  • 右值引用
    • 概念
    • 右值引用的意义
  • lambada表达式
  • 包装器
    • function包装器
    • bind包装器
  • 📓总结


📄前言

C++标准10年磨一剑,于2011年迎来了它真正意义上的第二个标准,C++11能更好地适用与系统开发和库开发,语法与更加的繁华与简单化,本篇文章将重点介绍其中的右值引用lambda表达式包装器

右值引用

概念

要讨论什么是右值引用前,得要分清什么是左值,什么是右值。

左值一般为位变量名或解引用的指针,左值可以出现在赋值符号的左边,也可以出现在赋值符号的右边。

右值一般位常量,表达式返回值,函数返回值,右值可以出现在赋值符号的右边,但不能出现在符号的左边,且右值不能取地址 ,右值引用就是对右值的引用,起别名。

下面的左值和右值的对比

int main()
{
	/*左值*/
	int i = 0, j = 0;
	const int n = 123;
	const char* str = "abcd";
	
	/*左值引用*/
	int& ii = i;
	const char*& rstr = str;
	const int& nn = n;

	/*右值*/
	10;
	i + n;
	max(n, j);

	/*右值引用*/
	int&& rri = 12;
	double&& rr2 = 12.12 / 1.1;
	
	return 0;
}

右值引用的意义

左值引用其最大用途就是可以不用拷贝参数直接将数值传给函数,从而我们再也不需要担心传值拷贝的效率低下了。

注意:move函数可以使左值强行转化成右值

vector<int>&& test(vector<int>&& nums)	//这里右值变成了左值
{
    printf("%p\n", &nums);	
    sort(nums.begin(), nums.end(), greater<int>());

    return std::move(nums);	//转化成右值
}

int main()
{
    vector<int> nums {1,2,3,4,5,6,7,8,9};
    printf("%p\n", &nums);
    test(std::move(nums));	//强制转化成右值
    printf("%p\n", &nums);
    
    return 0;
}

结果:
0x7ffc04e86810
0x7ffc04e86810
0x7ffc04e86810

lambada表达式

lambda的书写格式[捕捉列表] (参数列表) mutable -> return-type { 函数体 }

1.[捕捉列表]:捕捉列表可以捕捉上下文的变量供lambda函数使用,使用 = 符号表示捕捉的变量都是传值传递,& 表示都是引用传递,并且编译器根据[ ]来判断接下来的代码是否为lambda函数。
2. (参数列表):与普通函数的参数列表一样。
3. 普通情况下,lambda函数都是一个const函数,mutable可以取消器常量性
4. {函数体}:在函数体内可以使用参数列表或捕捉列表的变量。
5. return-type:lambda表达式会自动推导返回值,所以返回类型可写可不写

样例

int main()
{

	vector<int> nums{ 1,2,3,4,5 };
	sort(nums.begin(), nums.end(), [&](int& a, int& b) { return a > b; });

	int a = 3, b = 3;	//lambda表达式也可以使用auto表达式来定义。
	auto add = [](int a, int b) { return a + b; };
	int x = add(a, b);

	return 0;
}

包装器

function包装器

function包装器是用于解决函数模板可调用的类型太多,而导致的效率低下问题。

template<class F, class T>
T useF(F f, T x)
{
	static int count = 0;
	cout << "count:" << ++count << endl;
	cout << "count:" << &count << endl;
	return f(x);
}

double f(double i)
{
	return i / 2;
}

struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};

int main()
{
	// 函数名
	cout << useF(f, 11.11) << endl;
	// 函数对象
	cout << useF(Functor(), 11.11) << endl;
	// lamber表达式
	cout << useF([](double d)->double{ return d/4; }, 11.11) << endl;
	
	return 0;
}

允许上面程序会发现useF函数模板实例化了三份,而包装器就可以解决这个问题。

int main()
{
	// 函数名(函数指针)
	std::function<int(int, int)> func1 = useF;
	// 函数对象
	std::function<int(int, int)> func2 = Functor;
	// lamber表达式
	std::function<int(int, int)> func3 = [](const int a, const int b)
	cout << func1(1, 2) << endl;
	cout << func2(1, 2) << endl;
	cout << func3(1, 2) << endl;

	return 0;
}

bind包装器

bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。

bind原型

// 原型如下:
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2)
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);

bind可以调整函数的参数顺序

int func(int a, int b)
{
	cout << "a: " << a << endl;
	cout << "b: " << b << endl;
	return a / b;
}

int main()
{
	//_1 与 _2 是参数的顺序,在命名空间placeholders中定义。
	auto func1 = bind(func, placeholders::_2, placeholders::_1);
	cout << func1(5, 10) << endl;
}

给函数参数默认值

int func(int a, int b)
{
	cout << "a: " << a << endl;
	cout << "b: " << b << endl;
	return a / b;
}

int main()
{
	//_1 与 _2 是参数的顺序,在命名空间placeholders中定义。
	auto func1 = bind(func, 13, 6);
	cout << func1(5, 10) << endl;	//给定默认值后便不可修改。
	function<int(int, int)> func2 = bind(func, placeholders::_2, placeholders::_1);	//也可以和function一起使用
}

📓总结

📜博客主页:主页
📫我的专栏:C++
📱我的github:github

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

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

相关文章

高校人员信息管理系统C++

代码&#xff1a;https://mbd.pub/o/bread/ZZeZk5lx 一、基本内容论述 1、问题描述 某高校有四类员工&#xff1a;教师、实验员、行政人员、教师兼行政人员&#xff1b;共有的信息包括&#xff1a;编号、姓名、性别、年龄等。其中&#xff0c;教师还包含的信息有&#xff1a;所…

实现一个简单的网络通信下(udp)

时间过去好久了&#xff0c;先回忆一下上一篇博客的代码&#xff01;&#xff01; 目前来看&#xff0c;我们客户端发一条消息&#xff0c;我服务器收到这一条消息之后呢&#xff0c;服务器也知道了是谁给我发来的消息&#xff0c;紧接这就把这条消息放进buffer当中&#xff0c…

陀螺仪LSM6DSV16X与AI集成(1)----轮询获取陀螺仪数据

陀螺仪LSM6DSV16X与AI集成.1--轮询获取陀螺仪数据 概述视频教学样品申请通信模式管脚定义IIC通信模式速率生成STM32CUBEMX串口配置IIC配置CS和SA0设置串口重定向参考程序初始换管脚获取ID复位操作BDU设置设置量程和速率配置过滤链轮询读取数据主程序演示 概述 本文将介绍如何使…

【算法】单调栈题单——矩阵系列⭐

文章目录 题目列表84. 柱状图中最大的矩形&#xff08;单调栈找左右两边第一个更低的位置&#xff09;85. 最大矩形⭐⭐⭐⭐⭐解法1——使用柱状图的优化暴力方法解法2——单调栈 &#xff1a;归因到 84. 柱状图中最大的矩形 &#x1f402; 1504. 统计全 1 子矩形⭐解法1——枚…

关于媒体查询不能生效的原因

问题 今天写媒体查询&#xff0c;遇到了个问题&#xff0c;卡了很久&#xff0c;引入三个样式&#xff1a;mainPageCommon.css、mainPageBig.css、mainPageSmall.css。其中的两个样式可以生效&#xff0c;但是小尺寸的媒体查询不能生效&#xff0c;这里很奇怪&#xff01;&…

STM32F407-14.3.10-01PWM模式

PWM 模式 脉冲宽度调制模式可以生成一个信号&#xff0c;该信号频率由 TIMx_ARR⑩ 寄存器值决定&#xff0c;其占空比由 TIMx_CCRx⑤ 寄存器值决定。 通过向 TIMx_CCMRx 寄存器中的 OCxM⑰ 位写入 110 &#xff08;PWM 模式 1&#xff09;或 111 &#xff08;PWM 模式 2&#…

C++学习之路(十七)C++ 用Qt5实现一个工具箱(增加托盘图标并且增加显示和退出菜单)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《为屏幕颜色提取功能增加一个点击复制的功能》功能。今天我们增加一个比较正式点的功能&#xff0c;就是增加托盘图标并且增加显示和退出菜单&#xff08;越来越像回事了吧 &#x1f601; &#xff09;。下面我们就来…

ssm医院门诊互联电子病历管理信息系统源码和论文

摘 要 网络的广泛应用给生活带来了十分的便利。所以把医院门诊互联电子病历管理与现在网络相结合&#xff0c;利用java技术建设医院门诊互联电子病历管理信息系统&#xff0c;实现医院门诊互联电子病历的信息化。则对于进一步提高医院门诊互联电子病历管理发展&#xff0c;对…

【电机控制】PMSM无感foc控制(五)相电流检测及重构 — 单电阻采样

0. 前言 相电流采样再FOC控制中是一个关键的环节&#xff0c;鉴于成本和易用性&#xff0c;目前应用较多的相电流采样方式是分流电阻采样&#xff0c;包括单电阻、双电阻以及三电阻采样法。 本章节先讲解单电阻采样相电流的检测及重构技术&#xff0c;在下一章讲解双电阻和三电…

项目实战一-性能测试筑基

这里写目录标题 一、为什么程序会出现性能问题、性能问题是怎么出现的&#xff1f;二、功能测试和性能测试的区别是什么&#xff1f;三、核心性能指标1、用户角度核心a、响应时间&#xff1a;b、并发量 2、成本角度3、运维角度面试题、并发量和吞吐量得区别&#xff1f;a、吞吐…

Qt 如何操作SQLite3数据库?数据库创建和表格的增删改查?

# 前言 项目源码下载 https://gitcode.com/m0_45463480/QSQLite3/tree/main # 第一步 项目配置 平台:windows10 Qt版本:Qt 5.14.2 在.pro添加 QT += sql 需要的头文件 #include <QSqlDatabase>#include <QSqlError>#include <QSqlQuery>#include &…

【强化学习算法】Q-learning原理及实现

实现代码github仓库&#xff1a;RL-BaselineCode 代码库将持续更新&#xff0c;希望得到您的支持⭐&#xff0c;让我们一起进步&#xff01; 文章目录 1. 原理讲解1.1 Q值更新公式1.2 ε-greedy随机方法 2. 算法实现2.1 算法简要流程2.2 游戏场景2.3 算法实现 3. 参考文章 1. 原…

[架构之路-256]:目标系统 - 设计方法 - 软件工程 - 软件设计 - 架构设计 - 软件系统不同层次的复用与软件系统向越来越复杂的方向聚合

目录 前言&#xff1a; 一、CPU寄存器级的复用&#xff1a;CPU寄存器 二、指令级复用&#xff1a;二进制指令 三、过程级复用&#xff1a;汇编语言 四、函数级复用&#xff1a;C语言 五、对象级复用&#xff1a;C, Java, Python 六、组件级复用 七、服务级复用 八、微…

win10下使用内置Linux

Win10安装Ubuntu子系统 #推荐博客 https://www.cnblogs.com/xiaoliangge/p/9124089.html #推荐视频 https://www.bilibili.com/video/BV184411i7As?spm_id_from333.337.search-card.all.click #Ubuntu18.04安装教程 https://edu.csdn.net/skill/gml/gml-214229ddcc6a496ba175…

基于hadoop下的Kafka分布式安装

简介 Kafka是一种分布式流处理平台&#xff0c;它具有高吞吐量、可扩展性、可靠性、实时性和灵活性等优点。它能够支持每秒数百万条消息的传输&#xff0c;并且可以通过增加节点来增加吞吐量和存储容量。Kafka通过将数据复制到多个节点来实现数据冗余和高可用性&#xff0c;即使…

JAVA代码优化:Easy Excel(操作Excel文件的开源工具)

Easy Excel官网&#xff1a; EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com) https://easyexcel.opensource.alibaba.com/ Easy Excel的特点和优势&#xff1a; 简单易用&#xff1a;Easy Excel提供了简洁的API&#xff0c;使用起来非常方便。开发…

xxl-job(分布式调度任务)

简介 针对分布式任务调度的需求&#xff0c;市场上出现了很多的产品&#xff1a; 1)TBSchedule&#xff1a;淘宝推出的一款非常优秀的高性能分布式调度框架&#xff0c;目前被应用于阿里&#xff0c;京东&#xff0c;支付宝&#xff0c;国美等很多互联网企业的流程调度系统中。…

Linux 基本语句_14_信号灯实验

原理&#xff1a; Send进程通过建立共享内存区域&#xff0c;并向其中写入数据&#xff0c;Recive通过与共享内存连接读取其中的数据。 但是如果进程进行读取操作的时候其他进程再次写入会产生数据丢失&#xff0c;产生竞态&#xff0c;为了确保在某段时间内只有一个操作&…

【Node.js】Node.js环境下载与安装教程(Windows系统)

前言 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;可以让你使用JavaScript进行服务器端编程。本教程将向你展示如何在Windows系统上下载和安装Node.js环境。 下载 首先&#xff0c;你需要下载Node.js环境。 打开Node.js官方网站&#xff1a;https://no…

Leetcode2661. 找出叠涂元素

Every day a Leetcode 题目来源&#xff1a;2661. 找出叠涂元素 解法1&#xff1a;哈希 题目很绕&#xff0c;理解题意后就很简单。 由于矩阵 mat 中每一个元素都不同&#xff0c;并且都在数组 arr 中&#xff0c;所以首先我们用一个哈希表 hash 来存储 mat 中每一个元素的…