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

问题描述 投票:4回答:3

使用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;
}
c++ c++11 gcc lambda stl
3个回答
13
投票

尝试改变

(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 ...如果我没有错,则行为未定义,因此“不稳定行为”(以及分段错误)也是绝对可以理解的。


11
投票

这里的问题是你的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());

2
投票

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>;
    }
© www.soinside.com 2019 - 2024. All rights reserved.