2013-05-14 56 views
4

我有一个容器存储指针。我试图根据指针指向的相应对象中的数据成员以非递增顺序对这些指针进行排序。就我而言,很可能有很多对象对该数据成员具有相同的值。标准::排序与相同的元素给出分割错误

以下是说明问题的简短代码。对排序功能的调用会导致分段错误。奇怪的是,如果容器中有16个元素指向具有相同值的对象,则排序似乎有效。但是如果我有17个元素指向具有相同值的对象,它会给出一个seg故障。

任何人都可以请解释为什么发生这种情况?

#include <iostream> 
#include <algorithm> 
#include <deque> 

//some class 
class A { 
public: 
    double a; 
    A(double aval); 
}; 

A::A(double aval) : a(aval) {} 

//compare class 
struct cmp_A : std::greater_equal<A*> { 
    bool operator() (const A* x, const A* y) const; 
} cmp_A_obj; 

//greater_equal comparison 
bool cmp_A::operator() (const A* x, const A* y) const { 
    return (x->a >= y->a); 
} 

int main() { 
    std::deque<A*> Adeque; 
    //insert 17 A pointers into the container 
    for(int i = 1; i<=17; i++) { 
     Adeque.push_back(new A(5)); 
    } 

    //This call to sort gives a Segmentation fault 
    std::sort(Adeque.begin(), Adeque.end(), cmp_A_obj); 

    for(std::deque<A*>::iterator i = Adeque.begin(); i!= Adeque.end(); i++) { 
     std::cout << "|" << (*i)->a; 
    } 
    std::cout << std::endl; 
} 

回答

14

您的比较必须实行strict weak ordering。小于或等于不满足此。它应该等于“小于”或“大于”,如在运算符<>中实现的,例如整数。元素

平等是通过两次运用这个顺序确定:

(!cmp(a,b)) && (!cmp(b,a)); // if this is false, a == b 
+0

你或许应该改变“小于或大于”到“''<' or '>”不那么暧昧。 (小于或大于可以被解释为'!=') – Pubby 2013-05-14 05:45:01

+1

@Pubby我改述了答案的这一部分。我担心我的答案意味着必须超载'<' or '>'。 – juanchopanza 2013-05-14 05:47:33

+1

+10这对于一个不小心的人来说是一个巨大的陷阱。我自己已经被这个错误所困扰,并且造成这个问题的原因并不明显。恕我直言,它需要更好地记录在所有的STL参考。 – gavinb 2013-05-14 05:48:00