1

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

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::set 中:

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

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

4

2 回答 2

4

排序的。它是根据您存储在集合中的数据类型进行排序的,它是指向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

您可以看到将值添加到两个集合(第一行)的无序方式以及在这种情况下设置的指针与输入顺序匹配的方式(第二行)。这是因为地址是用于订购的,正如您从最后一部分显示订购地址的事实中看到的那样。

尽管如前所述,它可能不一定与输入顺序匹配,因为内存领域可能有些碎片化(作为一个示例)。

包含实际整数的集合(与指向整数的指针相反)清楚地按整数值本身(第三行)排序。

于 2013-09-04T00:56:06.323 回答
2

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

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

...
std::set<DataLine> data;
于 2013-09-04T00:55:36.247 回答