STL源码剖析学习之function call操作符(operator())

本文详细介绍了STL中使用函数指针和仿函数的原理,特别是operator()操作符的重载。通过具体代码示例展示了如何使用函数指针实现快速排序,并通过仿函数实现基本数学运算。文章深入浅出地阐述了两种方法的优劣和适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//STL之function call操作符(operator())
//学习目的:函数指针与仿函数、operator()重载
/*
函数指针有缺点,最重要的是它无法持有自己的状态(所谓局部状态,local states),
也无法达到组件技术中的可适配性(adaptability)----也就是无法再将某些修饰条件
加诸于其上而改变其状态。为此STL使用了仿函数,所谓仿函数就是使用起来像函数一样
的东西。如果你针对某个class进行operator()重载,它就成为一个仿函数,至于要成为
一个可配接的仿函数,还需要做一些额外的努力。
  
//本程序代码来源《STL源码剖析》
*/

//函数指针事例
/*
//file:lqsort.cpp
#include <cstdlib>
#include <iostream>
using namespace std;

int fcmp(const void* elem1, const void* elem2)
{
const int* i1 = (const int*)elem1;
const int* i2 = (const int*)elem2;

if (*i1 < *i2)
{
return -1;
}
else if (*i1 == *i2)
{
return 0;
}
else if (*i1 > *i2)
{
return 1;
}
return 0;
}

void main()
{
int ia[10] = {32, 93, 32, 23, 45, 87, 20, 67, 95, 49};

int i;
for (i = 0; i < 10; ++i)
{
cout << ia[i] << " ";
}
cout << endl;

qsort(ia, sizeof(ia)/sizeof(int), sizeof(int), fcmp);

cout << "after qsort:" << endl;
for (i = 0; i < 10; ++i)
{
cout << ia[i] << " ";
}


getchar();
}
*/

//仿函数,operator()
//file: lfunctor.cpp
#include <iostream>
using namespace std;

//由于operator()重载了,因此plus成了一个仿函数
template <class T>
struct plus 
{
T operator() (const T& x,const T& y) const { return x + y; }
};

template <class T>
struct minus
{
T operator() (const T& x, const T& y) const { return x - y; }
};

int main()
{
//以下产生仿函数对象
plus<int> plusobj;
minus<int> minusobj;

//以下使用仿函数,就像使用一般函数一样
cout << plusobj(3, 5) << endl;
cout << minusobj(3, 5) << endl;

//以下直接产生仿函数的临时对象(第一对小括号),并调用之(第二对小括号)
cout << plus<int>() (43, 50) << endl;
cout << minus<int>() (43, 50) << endl;

getchar();
}
<think>好的,我现在需要回答用户关于C++中operator()(int count) const的问题。用户之前已经询问过一段使用函数对象创建线程的代码,现在他们想了解这个操作符重载的具体内容。首先,我要确认用户的问题核心在哪里。他们可能对operator()的重载机制不太清楚,尤其是后面的const关键字的作用。 首先,我应该回顾一下用户提供的代码。在PrintTask类中,operator()被重载为一个接受int count参数的const成员函数。这个函数的作用是让类的实例可以像函数一样被调用,也就是所谓的仿函数(functor)。用户的问题集中在重载了什么,所以需要解释清楚这个操作符的作用和const在这里的意义。 接下来,我需要分解回答的结构。首先,解释operator()的重载,说明它允许对象像函数一样被调用。然后,说明参数int count的作用,这里是控制循环次数。最后,解释const关键字在这里的重要性,即保证该成员函数不会修改类的成员变量,确保线程安全。 需要注意的是,用户可能对C++的成员函数和const成员函数的概念不太熟悉,所以需要用简单明了的语言来解释。同时,结合之前的代码示例,说明为什么这里需要const,特别是在多线程环境下,避免数据竞争等问题。 可能还需要比较普通函数和函数对象的区别,强调函数对象可以封装状态,而这里的例子虽然没有状态,但使用const保证即使未来添加了成员变量,也不会被意外修改。此外,线程库在传递参数时的机制,如何将参数5传递给operator(),这也是用户可能关心的点。 需要检查是否有遗漏的关键点,比如为什么使用函数对象而不是普通函数,可能提到函数对象可以携带状态,但在这个例子中没有使用,不过仍然展示了这种方法的灵活性。同时,确保解释中没有错误,比如const成员函数是否可以修改mutable成员,但在这个例子中没有涉及,所以可能不需要深入。 总结回答的结构应该是:先指出operator()重载了函数调用操作符,使类成为仿函数;然后说明参数的作用;接着解释const的意义;最后结合代码示例说明整体工作机制和优势。这样分点回答可以让用户更清晰地理解每个部分的作用。</think>`operator()(int count) const` 是 C++ 中对**函数调用运算符**(Function Call Operator)的重载。具体来说,它实现了以下两个核心功能: --- ### 1. **重载 `operator()`** - **功能**: 允许类的对象像普通函数一样被调用,这类对象称为**函数对象**(Function Object)或**仿函数**(Functor)。 - **代码行为**: ```cpp PrintTask obj; obj(5); // 等价于 obj.operator()(5) ``` 通过重载 `operator()`,可以直接用 `对象(参数)` 的形式调用该运算符,使对象的行为类似函数。 - **意义**: 相比普通函数,函数对象可以**封装状态**(类成员变量),提供更灵活的行为(尽管本例中没有使用成员变量)。 --- ### 2. **尾部的 `const` 关键字** - **功能**: 声明该成员函数为**常量成员函数**(Const Member Function),承诺不会修改类的成员变量。 - **代码约束**: ```cpp void operator()(int count) const { // 函数内部不能修改类的非 mutable 成员变量 } ``` 若尝试修改成员变量,编译器会报错。 - **意义**: - 保证线程安全性:在多线程中,避免数据竞争(Data Race)。 - 明确语义:表示该操作是“只读”的,增强代码可读性。 --- ### 结合示例代码 在您的代码中: ```cpp std::thread t2(PrintTask(), 5); ``` - **`PrintTask()`**:创建一个匿名函数对象。 - **`5`**:传递给 `operator()` 的参数 `count`。 - **调用逻辑**: 线程 `t2` 会执行 `PrintTask::operator()(5)`,循环打印 5 次字符串。 --- ### 关键总结 | 组成部分 | 作用 | |--| | `operator()` | 使对象可像函数一样调用,支持面向对象的多态和状态封装 | | `int count` | 定义函数调用时的参数 | | `const` | 确保函数对象的“无副作用”行为,适合多线程等需要安全性的场景 | 这种设计模式广泛应用于 STL 算法(如 `std::sort` 的比较器)和异步编程中,是 C++ 泛型编程的重要基础之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值