我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++:函数对象,STL提供的函数对象,函数适配器详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++:函数对象,STL提供的函数对象,函数适配器详解

1 函数对象

1.函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)的方式使用一个类对象。

2.使用STL中提供的或自定义的迭代器和**函数对象,**配合STL的算法,组合出各种各样的功能。

3.通过函数对象而不使用函数指针,可以增加通用性,提高效率。

4.函数对象概念:泛化的函数

在这里插入图片描述

①将普通函数作为函数对象:传递函数名


#include <iostream>
#include <numeric> //包含accumulate算法
#include <functional>
#include <vector>
using namespace std;
int mult(int a, int b) {
    return a * b;
}
int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7 };
    const int N = sizeof(a) / sizeof(int); //用该式确定数组长度,定义为常量
    cout << "所有数累乘为:" << accumulate(a, a + N, 1, mult) << endl; //将普通函数作为函数对象,传递函数名
    //指针a,a + N也可以作为迭代器
    return 0;
}

②将重载了()运算符的类的对象作为函数对象:传递"类名()"


#include <numeric>
#include <iostream>
using namespace std;
class MultClass {
public:
    int operator ()  (int a, int b) const {
        return a * b;
    }
};
int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7 };
    const int N = sizeof(a) / sizeof(int); //确定数组a的长度
    cout << "所有数乘积为:" << accumulate(a, a + N, 1, MultClass()) << endl; //传输方式是类名(),输出5040
    //指针a,a + N也可以作为迭代器
    MultClass ss;
    cout << ss(100, 100); //输出10000
    return 0;
}

2 STL提供的函数对象

在这里插入图片描述

1.系统提供函数对象帮助实现基本功能。

2.accmulate算法接受二元函数对象,transform算法接受一元函数对象。

①STL库的multiplies


#include <iostream>
#include <functional>
#include <numeric>
using namespace std;
int main(){
	int a[] = { 1, 2, 3, 4, 5, 6, 7 };
	const int N = sizeof(a) / sizeof(int);
	cout << accumulate(a, a + N, 1, multiplies<int>()) << endl;//通过STL自带的函数对象multiplies实现乘法,注意要写数据类型<int>
	//指针a,a + N也可以作为迭代器
	return 0;
}

②STL库的二元谓词greater


#include <iostream>
#include <algorithm>
#include <functional> //包含greater
using namespace std;
int main() {
	int arr[] = { 24, 43, 5, 4, 62, 34, 7654, 22 };
	const int N = sizeof(arr) / sizeof(int);
	copy(arr, arr + N, ostream_iterator<int>(cout, "\t"));
	cout << endl;
	sort(arr, arr + N, greater<int>()); //包含在<algorithm>中,默认是升序
	copy(arr, arr + N, ostream_iterator<int>(cout, "\t"));
	return 0;
}

3 函数适配器

适配器顾名思义,让函数适配算法。

Unary Predicate:一元谓词

binary:二元的

bind:结合,(使)联合在一起

在这里插入图片描述

在这里插入图片描述

①找出第一个大于40的数,注意用数组和vector都可以


#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main()
{
    int a[] = { 30, 40, 50, 90, 20, 10 };
    const int N = sizeof(a) / sizeof(int);
    int *c = find_if(a, a + N, bind2nd(greater<int>(), 40));
    cout << *c << endl;
    return 0;
}

一般使用数组初始化向量vector,后续操作更方便


int main()
{
    int a[] = { 30, 40, 50, 90, 20, 10 };
    const int N = sizeof(a) / sizeof(int);
    vector<int> v (a, a + N); //用数组初始化vector
    vector<int>::iterator p = find_if (v.begin(), v.end(), bind2nd(greater<int>(), 40) );
    if (p == v.end())
        cout << "找不到" << endl;
    else
        cout << *p << endl;
    return 0;
}

find_if算法在STL中的原型声明为:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if(InputIterator first, InputIterator last, UnaryPredicate pred);
它的功能是查找数组[first, last)区间中第一个pred(x)为真的元素。
InputIterator、UnaryPredicate是用概念来做模板参数名

②利用prt_fun、not1、not2产生组合适配器


#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;
int g(int x, int y) { //实现类似greater的功能
    return x > y;
}
int main()
{
    int a[] = { 30, 90, 10, 23, 432, 656, 7, 78 };
    const int N = sizeof(a) / sizeof(int);
    vector<int> v(a, a + N);
    auto p1 = find_if(v.begin(), v.end(), bind2nd(ptr_fun(g), 40)); //找第一个大于40的数
    //ptr_fun将函数指针转换为函数对象,bind2nd将40作为二元函数对象的第二个参数
    if (p1 == v.end())
        cout << "no element" << endl;
    else
        cout << *p1 << endl;
    auto p2 = find_if(v.begin(), v.end(), not1(bind2nd(ptr_fun(g), 15))); //找第一个不大于15的数
    //not1对一元函数对象取逻辑反,find_if找到第一个令bind2nd取false的值
    if (p2 == v.end())
        cout << "no element" << endl;
    else
        cout << *p2 << endl;
    auto p3 = find_if(v.begin(), v.end(), bind2nd(not2(ptr_fun(g)), 15)); // 找第一个不大于15的数
    //not2对二元函数取逻辑反
    if (p3 == v.end())
        cout << "no element" << endl;
    else
        cout << *p3 << endl;
    return 0;
}

③成员函数适配器,类的成员函数要通过适配器转换为普通函数对象


#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
struct Car
{
	int id;
	Car(int id) {
		this->id = id;
	}
	void display() const {
		cout << "car " << id << endl;
	}
};
int main() {
	vector<Car*> pcars;
	vector<Car> cars;
	for (int i = 0; i < 5; i++)
		pcars.push_back(new Car(i)); //push_back() 在Vector最后添加一个元素(参数为要插入的值)
	for (int i = 5; i < 10; i++)
		cars.push_back(Car(i));
	cout << "elements in pcars: " << endl;
	for_each(pcars.begin(), pcars.end(), mem_fun(&Car::display));//for_each算法对每一个迭代器范围中的元素进行函数对象计算
	//men_fun适配后函数对象的参数为"对象的指针"
	cout << endl;
	for_each(cars.begin(), cars.end(), mem_fun_ref(&Car::display));
	//men_fun_ptr适配后函数对象的参数为"对象的引用"
	cout << endl;
	for (size_t i = 0; i < pcars.size(); ++i)
		delete pcars[i];
	return 0;
}

为什么不能同全局函数一样直接传递函数名而成员函数必须以 &类名::函数名 的方式,因为需要考虑static成员函数的情况。
mem_fun(member适配为function):将成员函数适配为普通函数对象,适配出来的函数需要对象的指针作为参数。
men_fun_ref:将成员函数适配为普通函数对象,适配出来的函数需要对象的引用作为参数。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注编程网的更多内容!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++:函数对象,STL提供的函数对象,函数适配器详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

STL 中有哪些函数可以使用 C++ 函数对象?

stl 中提供了多个函数可接受 c++++ 函数对象作为参数,用于操作集合或执行特定转换。这些函数包括:transform():使用指定函数对象转换集合的元素。for_each():对集合中的每个元素执行操作,使用指定的函数对象。sort(
STL 中有哪些函数可以使用 C++ 函数对象?
2024-04-25

C++ 11 和 C++ 14 中 STL 函数对象的改进?

stl 函数对象经历了重大改进,包括 c++++ 11 中的完美转发和移动语义,以及 c++ 14 中的函数指针封装和通用 lambda。这些改进增强了可用性、效率和灵活性,例如,通用 lambda 简化了排序函数对象的编写,只需使用 st
C++ 11 和 C++ 14 中 STL 函数对象的改进?
2024-04-25

如何在 C++ 中有效使用 STL 函数对象?

c++++ 中的 stl 函数对象提供了一种高效且灵活的方式来处理容器数据,包括一元函数对象(接受 1 个参数并返回结果)、二元函数对象(接受 2 个参数并返回结果)和仿函数(重载了函数调用运算符)。函数对象具有可重用性、可扩展性和性能优化
如何在 C++ 中有效使用 STL 函数对象?
2024-05-24

C++ 函数对象在 STL 中扮演什么角色?

函数对象在 stl 中的作用主要包括:1. 容器比较和排序(例如 std::sort、std::find_if);2. 算法自定义(通过自定义谓词或比较函数定制算法行为);3. 容器适配器(扩展容器功能)。此外,函数对象还用于函数器库、面向
C++ 函数对象在 STL 中扮演什么角色?
2024-04-25

如何使用 C++ 函数对象扩展 STL 算法?

可以通过使用函数对象来扩展 stl 算法,函数对象是具有调用运算符 (operator()) 的类或结构。只需要将函数对象作为算法的参数传递即可,例如使用 std::sort 算法排序容器时,可以传递 std::greater 函数对象作为
如何使用 C++ 函数对象扩展 STL 算法?
2024-04-25

C++ 中函数指针与函数对象的异同?

函数指针和函数对象都是处理函数作为数据的机制。函数指针是指向函数的指针,而函数对象是包含重载的 operator() 的对象。两者都可以捕获变量并创建闭包。不同之处在于,函数指针是原始类型,而函数对象是类;函数指针必须指向有效函数,否则会产
C++ 中函数指针与函数对象的异同?
2024-04-12

C++类与对象及构造函数析构函数基础详解

这篇文章主要为大家介绍了C++类与对象及构造函数析构函数基础详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-16

C++ 成员函数详解:对象方法与函数指针的比较

成员函数和函数指针的区别:语法:对象方法使用点语法,函数指针使用解引用运算符。隐式参数:对象方法有 this 指针,函数指针没有。可访问性:对象方法只能访问对象内数据,函数指针可访问任何标识符。效率:对象方法通常比函数指针慢,因需查找 th
C++ 成员函数详解:对象方法与函数指针的比较
2024-04-30

C++ 标准库中有哪些常用的 STL 函数对象?

c++++ stl 中提供了多种函数对象,可用于对元素进行比较、排序和操作。常见的函数对象包括用于升序排序的 less,用于降序排序的 greater,用于比较相等的 equal_to,以及用于绑定函数参数的 bind2nd 和 mem_f
C++ 标准库中有哪些常用的 STL 函数对象?
2024-04-25

STL 函数对象与 C++ 泛型编程之间的关系?

stl 函数对象是 c++++ 泛型编程的基础,两者相辅相成。stl 函数对象充当回调,在泛型算法中执行特定操作。1. 函数对象是类似于函数的类,拥有 operator() 方法。2. 泛型编程是编写独立于数据类型或算法的代码。3. stl
STL 函数对象与 C++ 泛型编程之间的关系?
2024-04-25

STL 中的函数对象如何处理异常?

stl的函数对象可处理异常。stl算法通过catch语句自动捕获函数对象抛出的异常并转发给调用算法的函数,从而确保异常的正确处理。STL 中的函数对象如何处理异常函数对象是 STL 中一种轻量级、可调用的类型,它可以在容器算法中作为操作元
STL 中的函数对象如何处理异常?
2024-04-26

C++ 函数对象在 STL 中的最佳实践是什么?

使用函数对象时,最佳实践为:使用函数指针作为替代方案,提高效率。采用 lambda 表达式创建匿名函数对象。理解函数签名,确保函数对象与 stl 算法预期一致。使用泛型函数对象提供灵活性。注意性能影响,必要时使用函数指针替代。C++ STL
C++ 函数对象在 STL 中的最佳实践是什么?
2024-04-25

C++ 中使用 STL 函数对象的常见错误和陷阱

stl 函数对象的常见错误和陷阱包括:忘记捕获默认成员变量。意外的值捕获。修改内部状态。类型不匹配。并发问题。C++ 中使用 STL 函数对象的常见错误和陷阱简介函数对象(函数式的对象)在 C++ 标准模板库 (STL) 中广泛使用。虽
C++ 中使用 STL 函数对象的常见错误和陷阱
2024-04-26

STL 函数对象与 C++ lambda 表达式的区别是什么?

函数对象和 lambda 表达式都是创建匿名函数的工具。主要区别在于:语法:函数对象使用类定义,而 lambda 表达式使用 [] 语法。作用域:函数对象可以在类外使用,而 lambda 表达式仅限于定义范围。捕捉:函数对象不能捕捉外部变量
STL 函数对象与 C++ lambda 表达式的区别是什么?
2024-04-25

C++面向对象中构造函数使用详解

学习过C语言的小伙伴知道:C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题,这篇文章主要介绍了C++面向对象中构造函数使用
2022-11-13

C++11的函数对象怎么使用

这篇文章主要介绍“C++11的函数对象怎么使用”,在日常操作中,相信很多人在C++11的函数对象怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++11的函数对象怎么使用”的疑惑有所帮助!接下来,请跟
2023-06-19

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录