C ++:std :: sort使用自定义谓词的已销毁对象?

时间:2011-03-15 16:19:08

标签: c++ sorting

使用std :: sort时,我遇到了一些奇怪的问题。如果我用stable_sort替换std :: sort,问题就会消失。

class Entry
{
public:
    Entry() : _date(0), _time(0), _size(0) {}
    Entry(unsigned int d, unsigned int t, unsigned int s) : _date(d), _time(t), _size(s) {}
    ~Entry() {_size=0xfffffffe;}

    unsigned int _date, _time, _size;

};

void initialise(std::vector<Entry> &vec)
    vec.push_back(Entry(0x3f92, 0x9326, 0x1ae));
    vec.push_back(Entry(0x3f92, 0x9326, 0x8a54));
   //....  + a large number of other entries
}

static bool predicate(const Entry &e1, const Entry &e2)
{
    // Sort by date and time, then size
    if (e1._date < e2._date )
        return true;
    if (e1._time < e2._time )
        return true;

    return e1._size < e2._size;
}

int main (int argc, char * const argv[]) {
    using namespace std;
    vector<Entry> vec;
    initialise(vec);
    sort(vec.begin(), vec.end(), predicate);

    vector<Entry>::iterator iter;
    for (iter=vec.begin(); iter!=vec.end(); ++iter)
        cout << iter->_date << ", " << iter->_time <<
                  ", 0x" << hex << iter->_size << endl;

    return 0;
}

我的想法是,我首先按日期和时间按大小对数据进行排序。但是,根据向量中的数据,我将在第一个对象的末尾打印出大小为0xfffffffe,表示已访问已销毁的对象,或者在排序期间出现seg错误。

(Xcode 3.2.4 - 64位intel目标)

任何想法? 我怀疑它与我的谓词有关,但我看不出它的生命是什么...... !! 这个页面似乎引用了同样的问题:

  

http://schneide.wordpress.com/2010/11/01/bug-hunting-fun-with-stdsort/

但他给出的原因(谓词需要定义一个严格的弱序)似乎在这里得到满足......

3 个答案:

答案 0 :(得分:3)

您的谓词满足严格的弱排序标准。看看你的功能并问问自己,如果e1的日期是 e2之后会发生什么,但是e1的时间是之前的 e2?

答案 1 :(得分:2)

我认为你的谓词应该是这样的:

static bool predicate(const Entry &e1, const Entry &e2)
{
    // Sort by date and time, then size
    return e1._date < e2._date || 
      (e1._date == e2._date && 
        (e1._time < e2._time || 
          (e1._time == e2._time && e1._size < e2._size)));
}

你写的是 - 如果e1._date>e2._date,第一个条件是假的,但第二个条件可能仍然是真的,函数仍会声称e1<e2可能不是你想要的。

答案 2 :(得分:1)

您的代码必须是:

static bool predicate(const Entry &e1, const Entry &e2)
{
    // Sort by date and time, then size
    if (e1._date != e2._date )
        return e1._data < e2._date;
    if (e1._time != e2._time )
        return e1._time < e2._time;
    return e1._size < e2._size;
}

如果e2的日期在e1之后,那么您的版本会继续比较时间和大小。这不是你想要的。这最终会混淆std :: sort,因为如果你交换e1和e2,你将得不到一致的答案。