答案:c++中通过仿函数、Lambda和函数指针自定义STL容器比较规则,实现灵活排序。1. 仿函数重载operator(),可携带状态且性能优,适用于set等容器;2. lambda表达式适合std::sort临时定义逻辑,但不能直接用于容器模板参数;3. 函数指针使用普通函数传参,灵活性差且有调用开销;4. 自定义类型需明确定义比较逻辑,如按学生分数排序,注意满足严格弱序避免未定义行为。

在C++中,自定义STL容器的比较函数是实现灵活排序和组织数据的关键。无论是使用 std::sort 对数组或vector排序,还是使用 std::set、std::map 等有序容器,都可以通过自定义比较规则来控制元素的排列顺序。
1. 仿函数(Functor)实现自定义比较
仿函数是重载了函数调用操作符 operator() 的类或结构体。STL 容器常用它作为比较器。
例如,定义一个仿函数让 std::set 按降序存储整数:
struct greater_cmp { bool operator()(int a, int b) const { return a > b; // 降序 } }; std::set<int, greater_cmp> s = {3, 1, 4, 1, 5}; // 遍历输出:5 4 3 1 1
仿函数的优势在于可携带状态,且编译期通常能被内联优化,性能较好。
立即学习“C++免费学习笔记(深入)”;
2. 使用Lambda表达式作为比较函数
C++11起支持lambda,适合临时定义简单逻辑。常用于 std::sort:
std::vector<int> vec = {3, 1, 4, 1, 5}; std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; // 降序排序 });
注意:lambda不能直接作为模板参数用于容器(如set),除非转换为function对象或使用auto(需配合变量模板),但通常推荐用仿函数或函数指针。
3. 函数指针方式
定义普通函数并传入其指针:
bool cmp_desc(int a, int b) { return a > b; } std::set<int, bool(*)(int, int)> s(cmp_desc);
函数指针灵活性较低,无法捕获上下文,且可能带来间接调用开销。
4. 自定义复杂类型的排序规则
对结构体或类进行排序时,需明确比较逻辑。例如按学生分数排序:
struct Student { std::string name; int score; }; struct cmp_student { bool operator()(const Student& a, const Student& b) const { return a.score > b.score; // 分数高者优先 } }; std::vector<Student> students = {{"Alice", 85}, {"Bob", 90}}; std::sort(students.begin(), students.end(), cmp_student{});
若用于set,则直接作为模板参数传入即可。
基本上就这些。掌握仿函数、lambda和函数指针的使用场景,就能灵活控制STL容器的排序行为。关键是要确保比较函数满足“严格弱序”(strict weak ordering),否则可能导致未定义行为。


