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

news2024/11/14 14:13:54

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 constexpr
  in_interval (int a, int b) noexcept: a_{a}, b_{b} {}
  // call operator:
  [[nodiscard]] constexpr
  bool 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.coloradmin.cn/o/1944723.html

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

相关文章

MATLAB绘制方波、锯齿波、三角波、正弦波和余弦波、

一、引言 MATLAB是一种具有很强的数值计算和数据可视化软件&#xff0c;提供了许多内置函数来简化数学运算和图形的快速生成。在MATLAB中&#xff0c;你可以使用多种方法来快速绘制正弦波、方波和三角波。以下是一些基本的示例&#xff0c;展示了如何使用MATLAB的命令来实现正弦…

centos系统mysql主从复制(一主一从)

文章目录 mysql80主从复制&#xff08;一主一从&#xff09;一、环境二、服务器master1操作1.开启二进制日志2. 创建复制用户3. 服务器 slave1操作4. 在主数据库中添加数据 mysql80主从复制&#xff08;一主一从&#xff09; 一、环境 准备两台服务器&#xff0c;都进行以下操…

入门C语言Day15——关系条件逻辑操作符

今天来学习操作符中的一些内容&#xff0c;主要讲的是关系&条件&逻辑操作符 1.关系操作符 首先要来了解一下什么是关系操作符&#xff0c;关系操作符其实就是关系运算符&#xff0c;关系运算符又和关系表达式有关。 C语言中用于比较的表达式&#xff0c;就被称为 “关…

google、windows自带语音识别中英文等实时字幕使用

2、自带实时字幕 1&#xff09;google浏览器自带 实时字幕 设置里可以设置&#xff1a; 有视频声音播放会弹出黑色文本框 下载其他语言包-比如中文&#xff1a; 测试 2&#xff09;windows11 辅助功能 实时字幕 &#xff08;直接快捷键打开&#xff1a;Win Ctrl L&#…

openmv学习笔记(24电赛笔记)

#opemv代码烧录清除详解 openmv的代码脱离IDE运行程序&#xff0c;只需要在IDE中将代码烧录道flash里面&#xff0c;断开IDE连接&#xff0c;上电之后&#xff0c;会自动执行main.py中的程序&#xff0c;IDE烧录的时候&#xff0c;会默认将程序后缀保存为 .py文件。 ​​​​​…

go语言day16 runtime包 临界资源 sync包

深入理解Java虚拟机到底是什么_java虚拟机是什么-CSDN博客 Golang-100-Days/Day16-20(Go语言基础进阶)/day17_Go语言并发Goroutine.md at master rubyhan1314/Golang-100-Days GitHub runtime 类似jvm&#xff0c;runtime包也提供了垃圾回收功能。 并且jvm实现了对线程创建销…

自动化网络爬虫:如何它成为提升数据收集效率的终极武器?

摘要 本文深入探讨了自动化网络爬虫技术如何彻底改变数据收集领域的游戏规则&#xff0c;揭示其作为提升工作效率的终极工具的奥秘。通过分析其工作原理、优势及实际应用案例&#xff0c;我们向读者展示了如何利用这一强大工具加速业务决策过程&#xff0c;同时保持数据收集的…

vuepress搭建个人文档

vuepress搭建个人文档 文章目录 vuepress搭建个人文档前言一、VuePress了解二、vuepress-reco主题个人博客搭建三、vuepress博客部署四、vuepress后续补充 总结 vuepress搭建个人文档 所属目录&#xff1a;项目研究创建时间&#xff1a;2024/7/23作者&#xff1a;星云<Xing…

Java响应式编程库Reactor的介绍和基本使用

关于响应式编程的概念和介绍可以参考: 响应式编程(Reactive Programming)是什么? Java语言中,RxJava和Reactor是实现响应式编程的两个最流行的库,因为 Spring 5 及更高版本中,Reactor 是 Spring WebFlux 的底层实现框架,用于构建响应式 Web 应用,所以相比而言,Reactor…

【docker】部署证书过期监控系统mouday/domain-admin

证书过期了再去部署证书容易被骂&#xff0c;就找了一个开源的证书过期系统来部署一下 过程 官方文档&#xff1a;https://domain-admin.readthedocs.io/zh-cn/latest/manual/install.html#docker 直接下载镜像是超时的&#xff0c;切换一下文档推荐的镜像源 新建docker配置…

WPF多语言国际化,中英文切换

通过切换资源文件的形式实现中英文一键切换 在项目中新建Language文件夹&#xff0c;添加资源字典&#xff08;xaml文件&#xff09;&#xff0c;中文英文各一个。 在资源字典中写上想中英文切换的字符串&#xff0c;需要注意&#xff0c;必须指定key值&#xff0c;并且中英文…

【QT】窗口|菜单栏|菜单项|工具栏|状态栏|浮动窗口

目录 ​编辑 QT窗口 窗口分类 菜单栏 创建菜单栏&#xff0c;菜单&#xff0c;菜单项 菜单栏 菜单 菜单项 添加分割线 添加槽函数 ​编辑 添加快捷键 工具栏 停靠位置 浮动属性 移动属性 添加快捷项 ​编辑 状态栏 ​编辑 添加标签 添加进度表 ​编辑…

【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !

目录 C语言指针精讲1. 什么是指针&#xff1f;1.1 指针的内存模型1.1.1 指针演示输出 1.2 指针运算1.2.1 指针算术运算输出1.2.2 指针与数组的关系输出 1.3 指针类型1.3.1 不同类型的指针示例输出1.3.2 void 指针输出 1.4 指针与内存管理动态内存分配输出 1.5 指针与内存泄漏1.…

手写RPC-令牌桶限流算法实现,以及常见限流算法

为什么需要服务限流、降级 分布式架构下&#xff0c;不同服务之间频繁调用&#xff0c;对于某个具体的服务而言&#xff0c;可能会面临高并发场景。在这样的情况下&#xff0c;提供服务的每个服务节点就都可能由于访问量过大而引起一系列问题&#xff0c;比如业务处理耗时过长、…

数据结构中的八大金刚--------八大排序算法

目录 引言 一&#xff1a;InsertSort(直接插入排序) 二&#xff1a;ShellSort(希尔排序) 三&#xff1a;BubbleSort(冒泡排序) 四&#xff1a; HeapSort(堆排序) 五&#xff1a;SelectSort(直接选择排序) 六&#xff1a;QuickSort(快速排序) 1.Hoare版本 2.前后指针版本 …

数组Arrays,排序算法,String类,Stringbulider,正则表达式

## 数组 排序 经典的三大排序&#xff1a;冒泡&#xff0c;选择&#xff0c;插入 &#xff08;一&#xff09;冒泡排序核心&#xff1a;数组中的 相邻 两项比较&#xff0c;交换&#xff08;正序or倒序&#xff09; 正序原理图&#xff1a; 代码实现&#xff1a; public s…

jmeter 重试机制

一、功能实现 我们在测试过程中&#xff0c;请求接口可能是因为请求超时&#xff0c;或者接口异常失败&#xff0c;导致整个测试链路验证失败&#xff0c;jmeter重试机制&#xff0c;这个时候就可以避免上述问题发生 二、配置 1、添加线程组 首先&#xff0c;确保你已经在测…

Python | Leetcode Python题解之第278题第一个错误的版本

题目&#xff1a; 题解&#xff1a; # The isBadVersion API is already defined for you. # def isBadVersion(version: int) -> bool:class Solution:def firstBadVersion(self, n: int) -> int:left, right 1, nwhile left < right:mid left (right - left) //…

power bi条件判断函数

power bi条件判断函数 1. iferror函数2. if 函数3. switch函数4. hasonefilter函数5. hasonevalue函数6. selectedvalue函数 1. iferror函数 遇到错误时使用指定数值替换注意&#xff1a;替换的必须是数值例子列 [销售数量]*[单价] 列 iferror([销售数量]*[单价],0) 列 ife…

昇思25天学习打卡营第17天|计算机视觉

昇思25天学习打卡营第17天 文章目录 昇思25天学习打卡营第17天ShuffleNet图像分类ShuffleNet网络介绍模型架构Pointwise Group ConvolutionChannel ShuffleShuffleNet模块构建ShuffleNet网络 模型训练和评估训练集准备与加载模型训练模型评估模型预测 打卡记录 ShuffleNet图像分…