排序操作后添加到 vector 的垃圾值

garbage value added to vector following a sort operation

我有一个 vector 称为键,用于排序,我有 struct comp :

typedef std::list<std::vector<WayPoint> >::iterator pathIt;
typedef std::pair<double, pathIt> Pair;
struct comp{
    bool operator()(const Pair& lhs,const Pair& rhs) const
    {
        return lhs.first*1000000 <= rhs.first*1000000;
    }
};
std::list<std::vector<WayPoint> > paths;
std::vector<Pair> keys;

在程序中,我对keys进行了std::sort操作:

std::sort(keys.begin(), keys.end(),comp());

我在 sort 之前和之后打印了容器(Pair 元素的第一个值),并注意到在排序之后一些垃圾被添加到 keys 中。 我在 compare function 做错了什么吗? 注意:我在 comp 函数中计算出,乘以 1000000 是比较双精度的好方法。对吧?

感谢

更新: 除了必须用 < 替换比较器中 <= 的问题外,我需要更多关于双值比较的说明:可能我很困惑,但为什么在 SO 分析中有这么多问题比较 double 值的方法?如果处理器可以正确比较双打,为什么严格建议不要使用 double 作为 std::map 中的键?我混淆了两个不相关的话题吗?上面的乘法是Unnecessary还是A wrong way to implement a necessary requirement?

我写了一个小测试程序看看是否可以重现您的问题,它对我来说工作正常。我想知道垃圾是否以其他方式引入,也许是在打印矢量内容时。这是我的测试代码:

#include <cstdio>

#include <vector>
#include <list>
#include <algorithm>

struct WayPoint {
    int x;
    WayPoint(int x);
};

typedef std::vector<WayPoint> Path;
typedef std::list<Path> PathList;
typedef std::pair<double,PathList::iterator> Pair;
typedef std::vector<Pair> PairList;

struct PairComp {

    bool operator()(const Pair& lhs, const Pair& rhs ) const {
        return lhs.first < rhs.first;
    }

};

int main(void) {

    PathList pathList{
        Path{WayPoint(1),WayPoint(2),WayPoint(3)},
        Path{WayPoint(4),WayPoint(5),WayPoint(6)},
        Path{WayPoint(7),WayPoint(8),WayPoint(9)},
        Path{WayPoint(10),WayPoint(11),WayPoint(12)}
    };

    PathList::iterator pathListIt = pathList.begin();
    Pair pair1{7.0,pathListIt++};
    Pair pair2{2.0,pathListIt++};
    Pair pair3{14.0,pathListIt++};
    Pair pair4{9.0,pathListIt++};
    PairList pairList{pair1,pair2,pair3,pair4};

    std::sort(pairList.begin(), pairList.end(), PairComp() );

    for (PairList::iterator it = pairList.begin(); it != pairList.end(); ++it) {
        Pair& pair = *it;
        std::printf("%f\n", pair.first );
    } // end for

} // end main()

WayPoint::WayPoint(int x) : x(x) {}

输出:

2.000000
7.000000
9.000000
14.000000

让我知道你的做法与我不同,看看我们是否能找出可能导致问题的原因。

编辑: 好的,这是一个修改后的程序,它使用了不正确的比较运算符并且 gua运行 有很多重复项:

#include <cstdio>
#include <cstdlib>

#include <vector>
#include <list>
#include <algorithm>

struct WayPoint {
    int x;
    WayPoint(int x);
};

typedef std::vector<WayPoint> Path;
typedef std::list<Path> PathList;
typedef std::pair<double,PathList::iterator> Pair;
typedef std::vector<Pair> PairList;

struct PairComp {

    bool operator()(const Pair& lhs, const Pair& rhs ) const {
        return lhs.first <= rhs.first;
    }

};

double getKey(void);

const int NUM = 30;

int main(void) {

    std::srand(time(0));

    PathList pathList;
    PairList pairList;

    pathList.push_back(Path({WayPoint(0)}));
    PathList::iterator it = pathList.begin();
    pairList.push_back(Pair(getKey(), it ));
    for (int i = 1; i < NUM; ++i) {
        pathList.push_back(Path({WayPoint(i)}));
        pairList.push_back(Pair(getKey(), ++it ));
    } // end for

    std::sort(pairList.begin(), pairList.end(), PairComp() );

    for (PairList::iterator it = pairList.begin(); it != pairList.end(); ++it) {
        Pair& pair = *it;
        std::printf("%f\n", pair.first );
    } // end for

} // end main()

WayPoint::WayPoint(int x) : x(x) {}

double getKey(void) {
    static double sample[] = {1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0};
    return sample[std::rand()%(sizeof(sample)/sizeof(sample[0]))];
} // end getKey()

对我有用,示例输出:

1.000000
1.000000
1.000000
1.000000
2.000000
2.000000
2.000000
2.000000
2.000000
2.000000
3.000000
3.000000
3.000000
3.000000
4.000000
4.000000
4.000000
4.000000
5.000000
5.000000
5.000000
5.000000
5.000000
5.000000
6.000000
6.000000
7.000000
8.000000
8.000000
8.000000

编辑:啊哈!我 运行 测试程序的修改版本多次,最终在 PairComp::operator() 中出现段错误,正如从 std::sort() 调用的那样。这是来自 gdb 的完整回溯(警告:后面是冗长的 C++ 回溯):

Program received signal SIGSEGV, Segmentation fault.
0x0000000100402144 in PairComp::operator()(std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > const&, std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > const&) const ()
(gdb) bt
#0  0x0000000100402144 in PairComp::operator()(std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > const&, std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > const&) const ()
#1  0x0000000100401f87 in bool __gnu_cxx::__ops::_Iter_comp_iter<PairComp>::operator()<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > > >(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >) ()
#2  0x00000001004042ea in __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > > std::__unguarded_partition<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__ops::_Iter_comp_iter<PairComp> >(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__ops::_Iter_comp_iter<PairComp>) ()
#3  0x0000000100404852 in __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > > std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__ops::_Iter_comp_iter<PairComp> >(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__ops::_Iter_comp_iter<PairComp>) ()
#4  0x00000001004041cd in void std::__introsort_loop<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, long, __gnu_cxx::__ops::_Iter_comp_iter<PairComp> >(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, long, __gnu_cxx::__ops::_Iter_comp_iter<PairComp>) ()
#5  0x00000001004041f0 in void std::__introsort_loop<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, long, __gnu_cxx::__ops::_Iter_comp_iter<PairComp> >(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, long, __gnu_cxx::__ops::_Iter_comp_iter<PairComp>) ()
#6  0x0000000100404b9e in void std::__sort<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__ops::_Iter_comp_iter<PairComp> >(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__ops::_Iter_comp_iter<PairComp>) ()
#7  0x00000001004049e4 in void std::sort<__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, PairComp>(__gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, __gnu_cxx::__normal_iterator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >*, std::vector<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > >, std::allocator<std::pair<double, std::_List_iterator<std::vector<WayPoint, std::allocator<WayPoint> > > > > > >, PairComp) ()
#8  0x00000001004012e8 in main ()

我也 运行 多次修改程序,但使用了正确的 (<) 比较运算符,而且它从未出现段错误。所以我认为我们已经确定了问题所在:不正确的比较运算符。

我想这里的一般教训是,当您违反盲(信任)算法所依赖的要求时,所有的赌注都会被取消。它可能会引入垃圾数据,可能会出现段错误,或者可能会为您提供正确的结果。你要小心了。

这是一个有趣的问题,为这个问题 +1。 :)

你的比较函数不正确。它计算小于或等于。比较器必须严格计算小于。如果您的矢量包含具有相同值的多个元素,这可能会导致错误。

我不知道这是否是您垃圾的来源,但这是我首先要解决的问题。如果这没有帮助,请在评论中告诉我。

此外,如评论中所述,比较器中的乘法完全没有必要。