C++ 中的仿函数:它们是什么以及如何简化代码?完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++ 中的仿函数是什么以及为什么需要它们?

\n\n

想象一下,您正在编写 C++ 代码,并且需要将行为(函数)传递给另一个函数,例如用于排序或数据过滤。经典的解决方案是函数指针。但它们有缺点:它们不存储状态,难以内联(inline),并且看起来有点过时。这时 C++ 中的仿函数(也称为 函数对象 或 C++ 函数对象)就登场了。

\n\n

仿函数是一个普通的类或结构体,其中重载了函数调用运算符 operator()。因此,此类的一个实例可以像普通函数一样使用。听起来很复杂?实际上,它是 C++ 中最优雅的工具之一。在 Stack Overflow 上,问题 "What are C++ functors and their uses?" 获得了数千次浏览——开发人员希望深入了解这个主题,以便编写更灵活、性能更高的代码。在本指南中,我们将系统地讲解所有内容:从基本语法到与 STL 结合使用的实际示例。

\n\n

基本语法:如何创建您的第一个仿函数

\n\n

创建仿函数只需三个步骤:

\n
    \n
  • 声明一个类或结构体。
  • \n
  • 在内部实现具有所需签名(参数和返回类型)的 operator()。
  • \n
  • 创建此类的对象并像函数一样调用它。
  • \n
\n\n

这是一个最简单的 C++ 仿函数示例,它将数字乘以二:

\n\n
#include <iostream>\n\nclass Multiplier {\npublic:\n    // 重载运算符 ()\n    int operator()(int x) const {\n        return x * 2;\n    }\n};\n\nint main() {\n    Multiplier mult;  // 创建一个函数对象\n    std::cout << mult(5) << std::endl; // 输出:10\n    std::cout << mult(10) << std::endl; // 输出:20\n    return 0;\n}
\n\n

请注意:mult(5) 看起来像普通函数调用,但实际上它是调用 mult.operator()(5)。编译器提供了语法糖,使代码变得简洁直观。

\n\n

主要优势:仿函数可以存储状态

\n\n

与普通函数或 lambda 表达式(在 C++11 之前)不同,C++ 函数对象 可以拥有自己的成员字段。这开启了巨大的可能性。例如,您可以创建一个仿函数,它不仅执行操作,还能记住被调用了多少次:

\n\n
#include <iostream>\n\nclass Counter {\nprivate:\n    int count = 0;\npublic:\n    int operator()() {\n        return ++count;\n    }\n    int getCount() const { return count; }\n};\n\nint main() {\n    Counter counter;\n    std::cout << counter() << std::endl; // 1\n    std::cout << counter() << std::endl; // 2\n    std::cout << counter() << std::endl; // 3\n    // 状态在调用之间保持!\n    return 0;\n}
\n\n

这个 带有状态的 C++ 仿函数示例 无法通过使用全局变量(这很糟糕)的简单函数来实现。仿函数优雅且安全地解决了这个问题。

\n\n

仿函数与 STL 算法:完美结合

\n\n

仿函数最强大的应用是与标准模板库(STL)中的算法一起使用。像 std::sort、std::find_if、std::for_each 这样的算法期望接收一个可调用对象(callable)。您可以将仿函数传递给它,它将执行所需的逻辑。

\n\n

示例:使用仿函数进行排序

\n\n

假设您有一个数字向量,并且希望按降序对它们进行排序。您可以编写自己的比较仿函数:

\n\n
#include <iostream>\n#include <vector>\n#include <algorithm>\n\nclass Descending {\npublic:\n    bool operator()(int a, int b) const {\n        return a > b; // 返回                

博客

书籍推荐