C++11 的继续学习

news2024/11/16 3:36:10

1.lambda 

我们如果想要给一个自定义的元素排序,那么应该怎么排呢

先举个例子:

struct Goods
{
	string _name;  // 名字
	double _price; // 价格
	int _evaluate; // 评价
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};
struct Comparepriceless
{
	bool operator()(const Goods& g1, const Goods& g2)
	{
		return g1._price < g2._price;
	}
};
int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };
	sort(v.begin(), v.end(), Comparepriceless());
}

这里的Comparepriceless(),这是在干什么呢:sort要接受的是一个函数,而我们现在Comparepriceless是一个类,所以是用它调用operator(),我们此时用的是仿函数,然后用匿名对象调用operator,但是不能用有名对象的operator(),这是因为你()要传参数,它需要的是这样的:这样才能调用到,但是我们仿函数会自动反过来调用

这是我们平常写的,如果学习了c++11的话我们有了新的写法,就是用lambda写 ,比较方便用于多个不同种类的那种,有利之处类似于多态那种感觉。

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement
}
1. lambda表达式各部分说明
[capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来
判断接下来的代码是否为lambda函数捕捉列表能够捕捉上下文中的变量供lambda
函数使用
(parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以
连同()一起省略
mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量
性。使用该修饰符时,参数列表不可省略(即使参数为空)。
->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回
值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推
{statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获
到的变量。
注意:
在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为
。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。
int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
		3 }, { "菠萝", 1.5, 4 } };
	for (auto e : v)
	{
		cout << e._name << " ";
	}
	cout << endl;
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool
		{
			return g1._price > g2._price;
		});
	for (auto e : v)
	{
		cout << e._name << " ";
	}
return 0;

}

 

2接着我们要详细写一下lambda的各种情况以及使用情况

int main()
{
	//最简单的lambda
	[] {};//从中我们可以知道 参数列表 返回类型 都是可以省略的
	int a = 10, b = 20, c = 30;
	//省略返回类型:
	auto d = [](int x, int y) {return x + y; };
	cout << d(a, b) << endl;
	
	//使用lambda 对于参数的两种方式
	auto e = [](int x, int y)->int//传参
		{
			return x + y;
		};
	cout << e(a, b)<<endl;

	auto la=[a, b]()->int//追踪 追踪到的是原变量的拷贝,具有cosnt性质
		{
			return a + b;
		};
	cout << la() << endl;

	//全追踪 
	auto f = [=] {return a + b + c; };
	cout << f() << endl;

	//全追踪 改变常量 只改变拷贝,实际改变需要引用
	auto g = [=]()mutable {a++; };

	//引用追踪 因为引用符号和取地址符号重复了,
	auto m = [&] {a++, b++, c++; };
	m();
	cout << a << " " << b << " " << c << endl;

}
3捕获列表说明
捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用
[var]:表示值传递方式捕捉变量var
[=]:表示值传递方式捕获所有父作用域中的变量(包括this)
[&var]:表示引用传递捕捉变量var
[&]:表示引用传递捕捉所有父作用域中的变量(包括this)
[this]:表示值传递方式捕捉当前的this指针
注意:
a. 父作用域指包含lambda函数的语句块
b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割
比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量
[&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量
c. 捕捉列表不允许变量重复传递,否则就会导致编译错误
比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
d. 在块作用域以外的lambda函数捕捉列表必须为空
e. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者
非局部变量都
会导致编译报错。
f. lambda表达式之间不能相互赋值,即使看起来类型相同
4:lambda与 函数对象(仿函数)
仿函数: 在类中重载了operator()运算符的类对象。
class Rate
{
public:
	Rate(double rate) : _rate(rate)
	{}
	double operator()(double money, int year)
	{
		return money * _rate * year;
	}
private:
	double _rate;
};
int main()
{
	// 函数对象
	double rate = 0.49;
	Rate r1(rate);
	r1(10000, 2);
	// lamber
	auto r2 = [=](double monty, int year)->double {return monty * rate * year;
		};
	r2(10000, 2);
	return 0;
}

二:function包装器

function包装器 也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。
#include<functional>
struct Functor
{
public:
	int operator() (int a, int b)
	{
		return a + b;
	}
};
int f(int a, int b)
{
	return a + b;
}

class Plus
{
public:
	static int plusi(int a, int b)//没有 this
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	//包装三种 函数指针 仿函数 lambda
	function<int(int, int)> f1 = f;
	function<int(int, int)>f2 = Functor();
	function<int(int, int)> f3 = [](int x, int y) {return x + y; };
}

让我们以一道题看看function 的作用:LCR 036. 逆波兰表达式求值 - 力扣(LeetCode)

class Solution {
public:
    int evalRPN(vector<string>& tokens)
    {
        stack<int> st;
        map<string,function<int(int,int)>> m =
        {
            {"+",[](int x,int y)->int{return x+y;}},
            {"-",[](int x,int y)->int{return x-y;}},
            {"*",[](int x,int y)->int{return x*y;}},
            {"/",[](int x,int y)->int{return x/y;}}
        };
        for(auto& e:tokens)
        {
            if(m.count(e))
            {
                int front=st.top();
                st.pop();
                int second=st.top();
                st.pop();
                int ret=m[e](second,front);
                 st.push(ret);
            }
            else
            {
                 st.push(stoi(e));
            }
        }
        return st.top();

    }
};

function 对非静态成员函数封装的时候,要考虑隐含的tiis指针 、

可以传指针,也可以传对象:原因是function不是直接传参调用函数的,它会把函数指针当作成员变量存储,然后再用对象或者指针来调用对应的函数,它会自动反过来调用。

class Plus
{
public:
	static int plusi(int a, int b)//没有 this
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};
int main()
{
	//function 主要是为了调用函数,就是封装函数,方便每次使用,
	//一共有三个 :仿函数 函数指针 lambda ,每次使用function的时候都需要传函数指针 不如用bind 也是调用函数
	
	function<double(Plus, double, double)> f6 = &Plus::plusd;//封装的是函数指针
	function<double(Plus*, double, double)> f7 = &Plus::plusd;
	//传的是对象 分为有名对象 匿名对象两种都可以传递
	cout << f6(Plus(), 1.1, 1.1) << endl;
	Plus pd;
	cout << f7(&pd, 1.1, 1.1) << endl;
}

 三:bind

std::bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器)接受一个可
调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。一般而
言,我们用它可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个(M
可以大于N,但这么做没什么意义)参数的新函数。同时,使用std::bind函数还可以实现参数顺
序调整等操作。
 bind 本质返回的一个仿函数对象
     调整参数顺序(不常用)
     _1代表第一个实参
     _2代表第二个实参
     ...
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;

int Sub(int a, int b)
{
	return (a - b) ;
}

int SubX(int a, int b, int c)
{
	return (a - b - c) ;
}

int main()
{
	auto a = bind(Sub, _1, _2);
	cout << a(10, 20) << endl;

	// 调整参数个数 (常用) 
	auto b = bind(Sub, 100, _1);//固定一个值 _1永远表示第一个你要传给的值,不是固定第一个
	cout << b(20) << endl;;
	
	auto c = bind(Sub, _1, 100);
	cout << c(20) << endl;

	auto d = bind(SubX, _1, _2, _3);
	cout << d(10, 20, 30) << endl;

	auto e = bind(SubX, 100, _1, _2);
	cout << e(20, 30) << endl;
	
	auto f = bind(SubX, _1, 100, _2);
	cout << e(20, 30) << endl;
	return 0;
}

最常用的就是用调整参数个数,还有就是调整参数顺序

_1 ,_2这种表示你开始传参(也就是除了那些固定的值的)的第一个,开始传参之后的第二个

还有就是要注意function 和bind不一样的区别,function要传有名对象,匿名对象或者有名对象的指针,bind传的函数指针并不用加括号,但是function在传匿名对象时候加了括号,注意括号的使用

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

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

相关文章

等额本息等额本金

1、贷款计算器 2024年最新版房贷利率计算器_LPR利率计算器 (K JSON) 贷款计算器 2、等额本息 接下来&#xff0c;我们可以用Python编写一个函数来计算每月还款额&#xff1a; import pandas as pddef amortization_schedule(principal, annual_interest_rate, years):"…

MySQL事务执行过程

一、MySQL一个查询语句执行过程如下图&#x1f53d; MySQL客户端查询&#xff0c;经过查询缓存、解析器、查询优化器、查询执行引擎&#xff0c;通过API接口查询&#xff0c;经过存储引擎&#xff0c;获取数据返回给客户端。 二、事务执行过程如下图&#x1f53d; 1、MySQL客户…

【生日视频制作】F900xr宝马摩托车提车交车仪式AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程F900xr宝马摩托车提车交车仪式AE模板修改文字特效广告生成神器素材祝福玩法AE模板工程 AE模板套用改图文教程↓↓&#xff1a; 怎么如何做的【生日视频制作】F900xr宝马摩托车提车交车仪式AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&a…

【变化检测】基于IFN建筑物(LEVIR-CD)变化检测实战及ONNX推理

主要内容如下&#xff1a; 1、LEVIR-CD数据集介绍及下载 2、运行环境安装 3、IFN模型训练与预测 4、Onnx运行及可视化 运行环境&#xff1a;Python3.8&#xff0c;torch1.12.0cu113 likyoo变化检测源码&#xff1a;https://github.com/likyoo/open-cd 使用情况&#xff1a;代…

00Mac 安装配置Python3虚拟环境(VirtualEnv、virtualenvwrapper扩展包)

文章目录 前言一、安装二、mac需要配置环境变量三、报错&#xff1a;workon: command not found 前言 本文主要记录&#xff0c;Mac 安装配置Python3虚拟环境&#xff08;VirtualEnv、virtualenvwrapper扩展包&#xff09;&#xff0c;windows直接执行命令即可&#xff0c;mac…

Arch - 演进中的架构

文章目录 Pre原始分布式时代1. 背景与起源2. 分布式系统的初步探索3. 分布式计算环境&#xff08;DCE&#xff09;4. 技术挑战与困境5. 原始分布式时代的失败与教训6. 未来展望 单体时代优势缺陷单体架构与微服务架构的关系总结 SOA时代1. SOA架构及其背景1. 烟囱式架构&#x…

论文翻译:arxiv-2024 Benchmark Data Contamination of Large Language Models: A Survey

Benchmark Data Contamination of Large Language Models: A Survey https://arxiv.org/abs/2406.04244 大规模语言模型的基准数据污染&#xff1a;一项综述 文章目录 大规模语言模型的基准数据污染&#xff1a;一项综述摘要1 引言 摘要 大规模语言模型&#xff08;LLMs&…

C#/.NET/.NET Core优质学习资料

前言 今天大姚给大家分享一些C#/.NET/.NET Core优质学习资料&#xff0c;希望可以帮助到有需要的小伙伴。 什么是 .NET? .NET 是一个免费的、跨平台的、开源开发人员平台&#xff0c;用于构建许多不同类型的应用程序。 使用 .NET&#xff0c;可以使用多种语言、编辑器和库来…

Java中Date类型上的注解

在日常开发中&#xff0c;涉及到日期时间类型Date和常用的注解DateTimeFormat和JsonFormat java.util.Date; org.springframework.format.annotation.DateTimeFormat; com.fasterxml.jackson.annotation.JsonFormat; 一 Date类型字段不使用注解 Data AllArgsConstructor N…

C语言程序设计——数组(一)

一、一维数组的定义和引用 数组:是一组具有相同数据类型的数据的有序集合。 1.1一维数组的定义 定义格式为: 类型说明符 数组名[常量表达式]; eg: int a[10]; 表示定义了一个整形数组,数组名为a,此数组有10个元素。 注:①数组名定名规则和变量名相同,遵循标识符…

【C++】STL学习——list模拟实现

目录 list介绍list结构介绍节点类的实现迭代器的实现构造函数运算符重载--运算符重载运算符重载!运算符重载*运算符重载->运算符重载 const迭代器的实现多参数模板迭代器list函数接口总览默认成员函数构造函数1构造函数2构造函数3 析构函数拷贝构造函数赋值重载函数 迭代器b…

八,SpringBoot Web 开发访问静态资源(附+详细源码剖析)

八&#xff0c;SpringBoot Web 开发访问静态资源(附详细源码剖析) 文章目录 八&#xff0c;SpringBoot Web 开发访问静态资源(附详细源码剖析)1. 基本介绍2. 快速入门2.1 准备工作 3. 改变静态资源访问前缀&#xff0c;定义为我们自己想要的4. 改变Spring Boot当中的默认的静态…

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext new ClassPathXmlApplicationContext("bean.xml"); } BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanFactory的功能相似&#xff0c;都是…

2024下学期学习总结加今日学习总结

Vue router Vue Router 是一个为 Vue.js 应用程序设计的官方路由管理器。它使你能够轻松地在 Vue 应用中实现页面导航&#xff0c;处理 URL 和视图的映射。 安装router 在运行框内输入 npm install vue-router4 //vue2专用 npm install vue-router3 //vue3专用 对router进…

uniapp数据缓存和发起网络请求

数据缓存 uni.onStorageSync同步的方式将数据存储到本地缓存 <template><button click"onStorageSync()">存储数据</button> </template><script setup>const onStorageSync () > {// 存储数据uni.setStorageSync(username, 张三)…

【验收交付体系文档】系统验收计划书,软件交付验收成套文档体系

软件系统验收计划书是确保新开发的软件系统符合预期要求并稳定运行的关键步骤。本计划书概述了验收过程的主要环节&#xff0c;包括系统功能的详细测试、性能评估、用户接受度测试以及文档完整性的核查。验收团队将依据项目需求规格说明书和合同要求&#xff0c;对系统进行全面…

axure判断

在auxre中我们也可以实现判断的功能&#xff0c;当目标等于什么内容时则执行下方的功能。 一、判断输入框中是否有值 画布添加一个输入框、一个文本标签删除其中内容&#xff0c;添加一个按钮&#xff0c;输入框命名为【文本显示】文本标签命名为【提示】 给按钮新增一个交互…

多个索引干扰导致索引失效如何解决

视频讲解&#xff1a;索引干扰导致索引失效如何解决_哔哩哔哩_bilibili 1 场景说明 表tb_order有订单状态order_status和创建时间create_time的索引。 现在业务的需求是&#xff0c;查询半年内&#xff0c;已支付订单状态的总数。SQL语句如下&#xff1a; SELECTCOUNT(1) FRO…

韦季李输入法_输入法和鼠标的深度融合

在数字化输入的新纪元&#xff0c;传统键盘输入方式正悄然进化。以往&#xff0c;面对实体键盘&#xff0c;我们常需目光游离于屏幕与键盘之间&#xff0c;以确认指尖下的精准位置。而屏幕键盘虽直观可见&#xff0c;却常因占据屏幕空间&#xff0c;迫使我们在操作与视野间做出…

Windows系统下安装JMeter

目录 一、官网下载JMeter 二、运行 JMeter 一、官网下载JMeter JMeter 官网安装地址 Apache JMeter - Apache JMeter™https://jmeter.apache.org/ 下载Windows版本 下载完成后 解压 二、运行 JMeter 打开bin目录 下面两个文件其中一个均可运行双击jmeter.bat 或者使用…