C++初学者指南-6.函数对象--函数对象

C++初学者指南-6.函数对象–函数对象

文章目录

  • C++初学者指南-6.函数对象--函数对象
    • 函数对象
    • 示例:区间查询
      • 区间内的查找
      • 区间划分(分组)
    • 指南
    • 标准库函数对象
      • 比较
      • 算术运算

函数对象

提供至少一个成员函数重载 operator() 的对象

class Multiplier {int m_;
public:// constructor:explicit constexpr Multiplier (int m) noexcept : m_{m} {}// call operator:constexpr int operator () (int x) const noexcept { return m_ * x; }
};

运行示例代码

可以像函数一样使用:

Multiplier triple{3};
int i = triple(2);  // i: 6

可以是有状态的:

class Accumulator {int sum_ = 0;
public:void operator () (int x) noexcept { sum_ += x; }int total () const noexcept { return sum_; }
};

Accumulator acc;
acc(2);
acc(3);
int sum = acc.total(); // sum: 5

可以用来定制行为:

// 比如使用标准库算法:
if ( std::any_of(begin(v), end(v), in_interval{-2,8}) ) …
//                     自定义函数对象 ^

示例:区间查询

class in_interval {int a_;int b_;
public:// constructor:explicit constexprin_interval (int a, int b) noexcept: a_{a}, b_{b} {}// call operator:[[nodiscard]] constexprbool operator () (int x) const noexcept {return x >= a_ && x <= b_;}
};

运行示例程序

// 生成对象
in_interval test {-10,5};
// 调用对象的 operator()
cout << test(1);   // true
cout << test(5);   // true
cout << test(-12); // false
cout << test(8);   // false

区间内的查找

在这里插入图片描述

std::vector<int> v {9,0,4,1,8,3,7,2,9};
// 查找符合[6,8]区间到的第一个值
// 在v的子范围内如图所示:
auto i = find_if(begin(v)+2, begin(v)+7, in_interval{6,8});
if (i != end(v)) {auto value = *i;  // int value = 8   auto index = distance(begin(v),i);  // int index = 4}
// 在v的所有元素中,查找符合[-4,4]区间的第一个值:
auto j = find_if(begin(v), end(v), in_interval{-4,4});
if (j != end(v)) {auto value = *j;  // int value = 0   auto index = distance(begin(v),j);  // int index = 1}

运行示例代码

区间划分(分组)

在这里插入图片描述
请注意,结果分区中元素的相对顺序不必与原始序列中的顺序相同。

std::vector<int> v {1,4,6,0,2,8,3,5};
auto i = partition(begin(v), end(v), in_interval{-1,2});
// print 1st partition:
for_each(begin(v), i, [](int x){ std::cout << x << ' '; }); 
// prints 1 2 0'
// print 2nd partition:
for_each(i, end(v), [](int x){ std::cout << x << ' '; }); 
// prints '6 4 8 3 5'
auto firstOf2ndPart = *i;  // 6
auto splitIndex = distance(begin(v),i);  // 3

运行示例程序

指南

避免有状态的 operator ()
有状态 = operator() 的当前结果依赖于之前对 operator() 的调用。
(例如,因为成员变量的值都用于计算结果,并且在同一次调用operator()中发生了变化。)
注意:许多(标准)算法并不保证传入的函数对象调用的顺序。特别是对于C++17引入的标准算法的并行版本,情况尤为如此。
这意味着传递一个有状态的函数对象可能会根据特定算法的具体实现和在将其传递给算法之前函数对象的状态而产生不同的结果。

  • 后续对operator()的调用应该是相互独立的。
  • 最好让 operator() 为 const,也就是完全不改变函数对象的状态。
  • 如果你在并行标准算法中使用非常量的 operator()(例如,用于跟踪状态信息),那么一定要确保它是线程安全的。例如,像 I/O 流这样的多线程共享资源必须妥善管理。

标准库函数对象

比较

#include <functional>
std::equal_to
std::not_equal_to
std::greater
std::less
std::greater_equal
std::less_equal
C++11  必须显式指定操作数类型:std::greater<Type>{}
C++14  不需要指定操作数类型:std::greater<>{}

#include <set>
#include <vector>
#include <functional>
#include <algorithm>
// 按降序设置 (默认是“升序”):
std::set<int,std::greater<>> s;
// 与` greater `而不是默认的` less `比较:
std::vector<int> v1 = {1,4,5};
std::vector<int> v2 = {1,2,5};
cout << lexicographical_compare(begin(v1), end(v1),begin(v2), end(v2), std::greater<>{});  // true

运行示例代码

算术运算

#include <functional>
std::plus
std::minus
std::multiplies
std::divides
std::modulus
std::negate
C++11  必须明确指定操作数类型:std::minus<Type>{}
C++14  不需要指定操作数类型:std::minus<>{}

示例:使用二元运算的左折叠
在这里插入图片描述
使用运算符 + 作为默认值,如果没有给出折叠操作作为第四个参数⇒结果是输入元素的总和。

#include <vector>
#include <functional>
#include <numeric>
std::vector<int> v {1,2,3,4,5};
// using default (operator +):
int sum = accumulate(begin(v), end(v), 0);  // sum  15
// using multiplication:
int product = accumulate(begin(v), end(v), 1, std::multiplies<>{});  // product = 120(1*1*2*3*4*5)

附上原文链接
如果文章对您有用,请随手点个赞,谢谢!^_^

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

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

相关文章

还在用if校验参数?SpringBoot使用validation优雅实现参数校验

&#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru (更多精彩内容可进入主页观看) &#x1f525; 系列专栏&#xff1a;《Docker容器化部署系列》 《Java每日面筋》 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 目录 一、前…

【c++】自定义函数分享:chooseBasedOnCondition函数,根据条件选择返回值

代码展示 int chooseBasedOnCondition(bool condition1, int value1, bool condition2, int value2) {if (condition1) {return value1;} else if (condition2) {return value2;} else {return 0; // 如果都不符合&#xff0c;默认返回0} }// 重载版本2&#xff1a;只接受一个…

鸿蒙APP架构及开发入门

1.鸿蒙系统 1.1 什么是鸿蒙 鸿蒙是一款面向万物互联时代的、全新的分布式操作系统。 在传统的单设备系统能力基础上&#xff0c;鸿蒙提出了基于同一套系统能力、适配多种终端形态的分布式理念&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机、PC、智能音箱、耳机、…

深入解析食堂采购系统源码:打造高效食材供应链APP的核心

本篇文章&#xff0c;笔者将从系统架构、关键模块、技术选型和优化策略等方面&#xff0c;深入解析食堂采购系统的源码&#xff0c;为您揭示打造高效食材供应链APP的核心要点。 一、系统架构 食堂采购系统通常采用分层架构&#xff0c;以保证系统的可维护性和扩展性。主要包括…

如何查看数据库的主机名和端口

查看数据库的主机名和端口的方法因数据库类型&#xff08;如MySQL、Oracle、SQL Server等&#xff09;和操作系统&#xff08;如Windows、Linux&#xff09;的不同而有所差异。以下是一些通用的方法和步骤&#xff1a; 一、查看数据库主机名 通过数据库管理工具&#xff1a; 对…

Android 列表或网格形式展示大量数据:RecyclerView(二):缓存复用

一、缓存复用 为什么要了解这个呢&#xff1f;当我们rv出现卡顿&#xff0c;出现闪烁的时候&#xff0c;你应该如何优化呢&#xff1f; 为什么有时候onCreateViewHolder会被调用&#xff1f;onBindVilewHolder会被调用呢&#xff1f; visiable的使用&#xff0c;会导致重新绘制…

Linux---git工具

目录 初步了解 基本原理 基本用法 安装git 拉取远端仓库 提交三板斧 1、添加到缓存区 2、提交到本地仓库 3、提交到远端 其他指令补充 多人协作管理 windows用户提交文件 Linux用户提交文件 初步了解 在Linux中&#xff0c;git是一个指令&#xff0c;可以帮助我们做…

jionlp根据词典进行行政区划补全

背景 需要对地址数据进行行政区划补全的,可以用下面的方法,当然是有条件限制的,只限于提供本省的词典和补全本身的地址数据,否则容易错乱 效果测试 lp = LocationParser() loc = 侨英街道乐海南里170号 res = lp(loc) print(res)1、安装或者更新 python安装 pip insta…

编写一个Chrome插件,网页选择文字后,右键出现菜单“search with bing”,选择菜单后用bing搜索文字

kimi ai 生成&#xff0c;测试可用&#xff0c;需要自行准备图标文件 创建一个简单的Chrome插件来实现选择文本后的搜索功能&#xff0c;你需要完成以下几个步骤&#xff1a; 创建插件的基础文件夹和文件&#xff1a; 创建一个文件夹用于存放插件的所有文件。在该文件夹中创建以…

Python爬虫技术 第18节 数据存储

Python 爬虫技术常用于从网页上抓取数据&#xff0c;并将这些数据存储起来以供进一步分析或使用。数据的存储方式多种多样&#xff0c;常见的包括文件存储和数据库存储。下面我将通过一个简单的示例来介绍如何使用 Python 爬取数据&#xff0c;并将其存储为 CSV 和 JSON 文件格…

LangChain4j-RAG高级-核心概念

RetrievalAugmentor整体概念 简单总结一下 LangChain4j中对于RetrievalAugmentor这里官方描述的比较模糊, 只在 DefaultRetrievalAugmentor章节给出来了一个灵感来源的文章(LangChain框架中的设计思路)和一个研究报告, 有兴趣可以看一下: Deconstructing RAGhttps://arxiv.o…

FRP配置内网穿透52版本以上适用

简述 适用frp配置内网穿透来说我们需要进行简单的区分&#xff0c;具有公网IP的服务器我们简称为服务端&#xff0c;内网的服务器我们可以简称为客户端&#xff0c;frp需要针对不同的服务器配置不同的文件 下载安装包 Linux下载地址 https://github.com/fatedier/frp/relea…

[Python][认识标准库][标准库][第三方库]详细讲解

目录 1.标准库1.认识标准库2.使用import导入模块 2.代码示例1.日期计算2.字符串操作1.翻转单词顺序2.旋转字符串3.统计是给定字符串前缀的字符串数目 3.文件查找工具 3.第三方库1.使用 pip2.示例&#xff1a;生成二维码3.示例&#xff1a;操作Excel4.示例&#xff1a;程序员鼓励…

Flink SQL 的工作机制

前言 Flink SQL 引擎的工作流总结如图所示。 从图中可以看出&#xff0c;一段查询 SQL / 使用TableAPI 编写的程序&#xff08;以下简称 TableAPI 代码&#xff09;从输入到编译为可执行的 JobGraph 主要经历如下几个阶段&#xff1a; 将 SQL文本 / TableAPI 代码转化为逻辑执…

svelte - 5. 动画

动画函数 函数作用使用场景示例引入的模块使用示例tweened运动动画,做到渐变的效果控制进度条速度svelte/motion函数:tweened(0, { duration: 400 })spring运动动画,用于频繁变化的值控制鼠标红点顺滑度svelte/motion函数:spring({ x: 50, y: 50 }, { stiffness: 0.1, damp…

华为ensp中ISIS原理与配置(超详细)

isis原理与配置 8-20字节&#xff1b; 地址组成&#xff1a;area id&#xff0c;system id&#xff0c;set三部分组成&#xff1b; system id占6个字节&#xff1b;sel占一个&#xff0c;剩下的为area id区域号&#xff1b; system id 唯一&#xff0c; 一般将router id 配…

操作系统面试知识点总结3

#来自ウルトラマンメビウス&#xff08;梦比优斯&#xff09; 1 内存管理概念 1.1 内存管理的基本原理和要求 内存&#xff1a;内存可存放数据&#xff0c;程序执行前需要先放到内存中才能被 CPU 处理 -- 缓和 CPU 与硬盘之间的速度矛盾。 功能&#xff1a; 内存空间的分配与…

深入学习H264和H265

目录 前言 一 什么是H264/H265&#xff1f; H.264 (MPEG-4 AVC) H.265 (HEVC) 二 为什么要学习H264和H265&#xff1f; 1. 深入理解视频压缩原理 2. 硬件优化与集成 3. 调试与故障排除 4. 持续的技术更新 三 NAL&#xff08;Network Abstraction Layer&#xff09;详解…

【Git】日常使用

参考 Git分支管理 如何使用 Git 进行多人协作开发 01 拉取最新分支 git pull origin main 02 创建分支 git checkout -b dev 03 在dev分支上进行更改 git commit git push dev 04 GitHub网页上提pull request&#xff0c;merge到main 05 删除分支 删除本地的dev分支和对…

【前端 11】初探DOM

JavaScript 对象 - DOM 初探 在Web开发中&#xff0c;DOM&#xff08;Document Object Model&#xff0c;文档对象模型&#xff09;是一个至关重要的概念。它不仅仅是一个API&#xff0c;更是Web页面与JavaScript代码之间的桥梁&#xff0c;允许开发者通过编程的方式动态地访问…