一次std::sort函数的踩坑记录

博客讲述了在使用STL的sort函数时,由于自定义比较函数逻辑错误,导致进程挂机的问题。问题源于当元素相等时比较函数返回true,这可能导致排序算法进入无限循环。解决方案是修正比较函数,确保相等元素返回false。此外,文章还介绍了std::sort的内部实现,包括快速排序、插入排序和堆排序的动态切换,以及如何避免递归过深的情况。

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

问题:最近收到一个反馈,有一个活动导致进程挂了,上去一瞧,发现居然是sort函数导致的宕机。。。
原因在于自定义的比较函数比较相等元素返回了true,函数大致如下:

bool cmp(const A& obj1, const A& obj2)
{
	return obj1.val >= obj2.val;
}

问题的原因:算是一个坑了。使用std::sort时,比较函数如果是大于等于或小于等于,可能会导致越界行为发生

问题的解决:需要把比较函数的逻辑修改为当元素相等时返回false,才能避免该类问题,修改后的函数如下:

bool cmp(const A& obj1, const A& obj2)
{
	return obj1.val > obj2.val;
}

std::sort函数底层原理
STL的sort算法,数据量大时采用QuickSort快排算法,分段归并排序。一旦分段后的数据量小于某个门槛(16),为避免QuickSort快排的递归调用带来过大的额外负荷,就改用Insertion Sort插入排序。如果递归层次过深,还会改用HeapSort堆排序。

### C++ 中 `std::sort` 使用的仿函数C++ 中,`std::sort` 函数可以通过自定义比较器来改变默认的升序排序行为。这个比较器可以是一个函数指针或者一个仿函数(functor)。仿函数是一种重载了括号运算符 (`operator()`) 的类对象,因此可以像调用普通函数一样被调用。 #### 定义仿函数 为了创建用于 `std::sort` 的仿函数,通常会定义一个小的结构体或类,并在这个结构体内实现 `operator()` 方法: ```cpp struct DescendingOrder { bool operator()(const int& lhs, const int& rhs) const { return lhs > rhs; } }; ``` 上述代码片段展示了如何编写一个简单的降序排列整数数组所需的仿函数[^1]。 #### 应用仿函数于 `std::sort` 一旦有了这样的仿函数,就可以将其作为第三个参数传递给 `std::sort` 来控制排序逻辑: ```cpp #include <algorithm> #include <vector> int main() { std::vector<int> numbers = {5, 3, 8, 7, 2}; // 使用仿函数进行降序排序 std::sort(numbers.begin(), numbers.end(), DescendingOrder()); return 0; } ``` 这段程序先初始化了一个包含五个元素的向量,接着利用之前定义好的 `DescendingOrder` 类型的对象来进行降序排序操作。 #### Lambda 表达式的替代方案 除了显式地声明仿函数外,在现代 C++ (C++11 及以后版本) 中还可以采用 lambda 表达式简化这一过程: ```cpp #include <algorithm> #include <vector> int main() { std::vector<int> numbers = {5, 3, 8, 7, 2}; // 使用lambda表达式代替仿函数进行降序排序 std::sort(numbers.begin(), numbers.end(), [](const int &a, const int &b){return a>b;}); return 0; } ``` 这里展示了一种更加简洁的方式——通过匿名函数即 lambda 表达式直接提供比较规则而无需额外定义新的类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值