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、ポインターを使用しないでください。オブジェクト自体を格納します。

2 つのセットを作成する次のコードから、同様の効果を確認できます。1 つ目は整数ポインタのセットで、2 つ目は実際の整数のセットです。

#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

値が 2 つのセットに追加される順不同の方法 (1 行目) と、この場合のポインター セットが入力の順序と一致する方法 (2 行目) を確認できます。これは、最後のセクションに順序付けされた住所が表示されていることからわかるように、住所が順序付けに使用されているためです。

ただし、前述のように、メモリ アリーナは多少断片化されている可能性があるため (一例として)、必ずしも入力順序と一致するとは限りません。

(整数へのポインターではなく) 実際の整数を含むセットは、整数値自体によって明確に並べ替えられます (3 行目)。

于 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 に答える