为什么我的std :: set没有排序?

时间:2013-09-04 00:47:05

标签: c++ boost set

我有一个类来存储如下所示的数据:

class DataLine
{
public:
   std::string name;
   boost::posix_time::time_duration time;
   double x, y, z;

   DataLine(std::string _name, boost::posix_time::time_duration _time, double _x,
            double _y, double _z); //assign all these, not going to do it here

   bool operator < (DataLine* dataLine) { return time < dataLine->time; }
}

然后我读了一堆数据并将它插入到std ::对象集中:

std::set<DataLine*> data;
data.insert( new DataLine(newname, newtime, newx, newy, newz) );
//...insert all data - IS OUT OF ORDER HERE

然后我运行我的数据并用它做任务,同时将新元素添加到集合中。

boost::posix_time::time_duration machineTime(0,0,0);

for(std::set<DataLine*>::reverse_iterator it = data.rbegin(); it != data.rend(); ++it)
{

    if(machineTime < (*it)->time)
    {
       machineTime = (*it)->time;
    }

    machineTime += processDataLine(*it); //do stuff with data, might add to append list below

    for(std::vector<AppendList*>::iterator iter = appendList.begin(); iter != appendList.end(); ++iter)
    {   
        data.insert( new DataLine( (*iter)->name, machineTime, 
                                  (*iter)->x, (*iter)->y, (*iter)->z); );

    }
}

当我尝试在插入元素之前和之后循环遍历数据集时,我的所有数据都不正常!使用

循环时会输出一些时间
for(std::set<DataLine*>::iterator it = data.begin(); it != data.end(); ++it)
{
   std::cout << std::endl << (*it)->time;
}


14:39:55.003001
14:39:55.003002
14:39:55.001000
14:39:59.122000
14:39:58.697000
14:39:57.576000
14:39:56.980000

为什么这些时间不按顺序排序?

2 个答案:

答案 0 :(得分:4)

已排序。它根据您存储在集合中的数据类型进行排序,该数据类型是{em>指针到DataLine。换句话说,它将根据对象的内存中的位置进行排序,这可能是可能创建顺序(但可能不是,取决于内存分配函数在您的实现中的工作方式)。

如果要根据DataLine类型本身进行排序,请不要使用指针。存储对象本身。

您可以从以下代码中看到类似的效果,该代码会创建两个集合。第一个是一组整数指针,第二个是一组实际整数:

#include <iostream>
#include <iomanip>
#include <set>
using namespace std;

int main (void) {
    set<int*> ipset;
    set<int> iset;

    cout << "inserting:          ";
    for (int i = 0; i < 10; i++) {
        int val = (i * 7) % 13;
        cout << ' ' << setw(2) << val;
        ipset.insert (new int (val));
        iset.insert (val);
    }
    cout << '\n';

    cout << "integer pointer set:";
    for (set<int*>::iterator it = ipset.begin(); it != ipset.end(); ++it)
        cout << ' ' << setw(2) << **it;
    cout << '\n';

    cout << "integer set:        ";
    for (set<int>::iterator it = iset.begin(); it != iset.end(); ++it)
        cout << ' ' << setw(2) << *it;
    cout << '\n';

    cout << "integer pointer set pointers:\n";
    for (set<int*>::iterator it = ipset.begin(); it != ipset.end(); ++it)
        cout << "   " << *it << '\n';
    cout << '\n';

    return 0;
}

运行该代码时,您会看到以下内容:

inserting:            0  7  1  8  2  9  3 10  4 11
integer pointer set:  0  7  1  8  2  9  3 10  4 11
integer set:          0  1  2  3  4  7  8  9 10 11
integer pointer set pointers:
   0x907c020
   0x907c060
   0x907c0a0
   0x907c0e0
   0x907c120
   0x907c160
   0x907c1a0
   0x907c1e0
   0x907c220
   0x907c260

您可以看到将值添加到两个集合(第一行)的无序方式以及此情况下指针设置的方式与输入顺序(第二行)匹配。那是因为地址是用于排序的地方,因为你可以看到最后一节显示了有序地址。

虽然如上所述,它可能必然匹配输入顺序,因为内存竞技场可能有点碎片(作为一个例子)。

包含实际整数的集合(与整数指针相对)显然按整数值本身排序(第三行)。

答案 1 :(得分:2)

您需要像下面一样定义成员operator <,并将对象保存在std::set而不是原始指针中。因为对于原始指针,默认的比较标准基于指针值本身。

bool operator < (const DataLine &dataLine) const
{ 
   return time < dataLine.time;
}

...
std::set<DataLine> data;