如果比较函数不是运算符<,为什么std::sort会崩溃;
Why will std::sort crash if the comparison function is not as operator <?
下面的程序是用VC++2012编译的。
#include <algorithm>
struct A
{
A()
: a()
{}
bool operator <(const A& other) const
{
return a <= other.a;
}
int a;
};
int main()
{
A coll[8];
std::sort(&coll[0], &coll[8]); // Crash!!!
}
如果我将return a <= other.a;
更改为return a < other.a;
,那么程序将按预期运行,无一例外。
为什么?
std::sort
需要一个满足严格弱排序规则的分类器此处
因此,你的比较器说a < b
当a == b
不遵循严格弱排序规则时,算法可能会崩溃,因为它将进入无限循环。
xorguy的答案非常好。
我只想添加一些来自标准的报价:
25.4排序和相关操作[算法排序]
为了使25.4.3中描述的算法以外的算法正确工作,comp必须在值上引入严格的弱排序
术语strict指的是不可伸缩关系(!comp(x,x)对于所有x)的要求,而术语weak则指的是那些不如全序强,但比偏序强的要求。
所以xorguy很好地解释了这一点:当a == b
不遵循严格弱排序规则时,comp
函数说a < b
。。。
代码的问题是访问无效内存。代码
coll[8]
尝试访问最后一个数组元素之后的元素(最后一个元素索引为7)。我建议使用std::array,而不是普通的C数组。
std::array<A, 8> a;
// fill it somehow
std::sort(a.begin(), a.end());
相关文章:
- 为什么 std::unique 不调用 std::sort?
- 为什么std::valarray不是算术的
- 为什么std::async使用同一个线程运行函数
- 为什么std::isnan 不是 constexpr?
- 为什么 std::optional::operator=(U&&) 要求你是非标量类型?
- 为什么 std::function 可以作为 std::not2 的参数?
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 为什么std::vector比数组慢
- 为什么std::copyable包含std::moveable
- 为什么std::to_string()没有模板化
- 为什么std::vector和std::valarray初始化构造函数不同
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 为什么 std::span 缺少 cbegin 和 cend 方法?
- 为什么 std::itrator 无法访问该函数
- 为什么 std::reduce 需要交换性?
- 为什么 std::equal_to会导致动态分配?
- 为什么 std::绑定错误参数可以成功?
- 为什么 std::lerp 不适用于任何已实现所需操作的类型?
- 为什么 std::next 在以空地图开头馈送时卡住