GCC的std :: sort与lambdas的不稳定行为

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GCC的std :: sort与lambdas的不稳定行为相关的知识,希望对你有一定的参考价值。

使用GCC 6.1.0编译时,以下代码生成分段错误。奇怪的是,错误是一致的,但不会出现较小的尺寸或略微不同的比较表达式。你们有什么想法吗?

#include <vector>
#include <algorithm>
#include <iostream>
int main() {
    int n = 1000;   
    std::vector<std::pair<double, double>> vec;
    for(int i = 0; i < n; i++) {
        vec.push_back(std::make_pair<double, double>((7*i)%3, (3*i)%5));
    }
    std::sort(vec.begin(), vec.end(), [](std::pair<double, double> const & p1, std::pair<double, double> const & p2) {return (p1.first < p2.first) || ((p1.first==p2.first)&& (p1.second <= p2.second));}); 
    return 0;
}
答案

尝试改变

(p1.second <= p2.second)

(p1.second < p2.second)

我的意思是...... std::sort()需要一个比较器返回true iff(当且仅当)第一个参数(p1)严格低于第二个参数(p2)。那就是:当false等于p1时,必须返回p2

如果您的考试是

   (p1.first < p2.first)
|| ((p1.first==p2.first)&& (p1.second <= p2.second))

true等于p1时,你也获得p2

true等于p1时,使用比较器返回p2 ...如果我没有错,则行为未定义,因此“不稳定行为”(以及分段错误)也是绝对可以理解的。

另一答案

这里的问题是你的lambda不符合Compare的标准要求,这要求严格的弱排序:

  • 严格意味着!comp(x, x)必须是序列中每个truex,这不是你的自定义比较器(lambda)的情况,因为comp(x, x) == true为你的情况下每个xx.first == x.first && x.second <= x.second)。

你应该将p1.second <= p2.second更改为p1.second < p2.second,或者使用std::pair的标准比较运算符:

std::sort(vec.begin(), vec.end());
另一答案

Libstdc ++有一个debug mode,可以通过定义宏_GLIBCXX_DEBUG来启用。

$ g++-6 b.cc -D_GLIBCXX_DEBUG && ./a.out
/usr/include/c++/6/bits/stl_algo.h:4737:
Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

Objects involved in the operation:
    instance "functor" @ 0x0x7ffe48ba5a20 {
      type = main::{lambda(std::pair<double, double> const&, std::pair<double, double> const&)#1};
    }
    iterator::value_type "ordered type" {
      type = std::pair<double, double>;
    }

以上是关于GCC的std :: sort与lambdas的不稳定行为的主要内容,如果未能解决你的问题,请参考以下文章

在 clang 和 gcc 中移动可分配的 lambda

错误“lambda不是从'std :: function'派生的

错误“lambda 不是从 'std::function' 派生的

lambda 如何在 MSVC2017 15.9.3 中使用 /std:c++17 中的静态局部错误返回值?

对空向量进行 std::sort [关闭]

在 lambda 中捕获 std::array