C++预定义函子使用差异:为何算法需实例化而容器适配器无需?
为什么C++预定义函子在算法和容器适配器中的使用方式不同?
核心原因很简单:算法需要的是可调用的函子实例,而容器适配器需要的是函子的类型。
1. 算法(如std::accumulate)需要函子实例
像std::accumulate这类算法是函数模板,它们的参数要求是一个可调用对象(可以是函数指针、lambda、函子实例等)。算法内部会直接调用这个对象的operator()来完成逻辑。
比如std::plus<>是一个类模板,它本身是个类型,不是可调用的对象。你必须用std::plus<>()创建一个实例,才能让算法调用它的operator()来做加法:
#include <vector> #include <numeric> int main() { std::vector<int> nums = {1, 2, 3, 4}; // 必须传std::plus<>()实例,算法才能调用它的operator() int total = std::accumulate(nums.begin(), nums.end(), 0, std::plus<>()); return 0; }
如果直接传std::plus<>(类型),编译器会报错——因为函数参数不能是类型,必须是具体的对象。
2. 容器适配器(如std::priority_queue)需要函子类型
std::priority_queue这类容器适配器是类模板,它的模板参数是用来指定“比较器的类型”。适配器会在内部默认构造这个类型的实例,或者允许你在构造时手动传入一个实例。
比如std::greater<>是比较器的类型,你把它作为模板参数传给std::priority_queue,是告诉适配器:“用这个类型的对象来比较元素大小”。适配器会自己创建std::greater<>的实例来工作:
#include <queue> int main() { // std::greater<>是类型,作为模板参数指定比较器的类型 std::priority_queue<int, std::vector<int>, std::greater<>> min_heap; min_heap.push(3); min_heap.push(1); min_heap.push(2); // 输出1,因为用了std::greater<>做比较,是小顶堆 return min_heap.top(); }
当然你也可以手动传一个std::greater<>的实例给适配器的构造函数,但模板参数依然是类型:
std::greater<> comp; std::priority_queue<int, std::vector<int>, std::greater<>> min_heap(comp);
一句话总结
- 算法是函数,要的是“能直接用的工具(实例)”;
- 容器适配器是类,要的是“工具的型号(类型)”,然后自己造工具或者用你给的工具。
内容的提问来源于stack exchange,提问作者Mikhail
相关产品推荐
相关产品推荐

