4

まあ、それが可能かどうかはわかりませんが、次のようになります。

struct stPiece
{
  /* some stuff */
  stPiece *mother; // pointer to the piece that created this one
};

vector<stPiece> pieces;

'mother'によって参照されているピースを、そのポインターだけを参照して、ピースから消去することは可能ですか?どのように?

それは他の参照を台無しにしますか?(つまり、それがベクトルの最後の要素でない場合は、次の要素を他のメモリ位置にシフトし、他の「*母」は一定のままにします)。もちろん、すべての子の部分が削除されると想定しています(したがって、同じ母親に向かうポインターを更新する必要はありません)。

ありがとう!

4

5 に答える 5

2

motherポインタがベクトルの要素を直接指している場合pieces、あらゆる種類の問題が発生します。

から要素を削除するpiecesと、より高いインデックスにある要素のすべての位置がシフトします。要素を挿入しても、すべてのポインタが無効になる可能性があります。これは、ベクトルが内部配列を再割り当てする必要がある場合があり、すべての要素がメモリ内の新しい位置に転送される可能性があるためです。

主な質問に答えるには、ポインタを持っている要素を直接削除することはできません。最初にベクトルを検索して見つけるか、ベクトル内のインデックスを計算する必要があります。

ポインタをpiecesasに格納せずmother、代わりに要素のインデックスを使用すると、少し堅牢になるため、少なくとも新しい要素を挿入しても、既存motherの要素が破損することはありません。ただし、から削除すると、pieces要素は新しいインデックスにシフトされます。

std::listforを使用し、piecesそれにイテレータを格納するmotherことで解決できる場合があります。std::listそのリストの他の要素が削除/追加された場合、のイテレータは無効になりません。異なる要素が同じである可能性があるmother場合でも、要素を削除するタイミングを見つけるのに問題があります。motherおそらく使用boost::shared_ptrする方が簡単です。

于 2010-01-14T05:24:54.500 に答える
2

データ構造全体がどのように編成され、結果がどうなるかは正確にはわかりませんが、その要素とベクトル自体へのポインターを使用することで、ベクトルから要素を消去することは完全に可能です。最初にポインタをイテレータに変換する必要があります。たとえば、ベクトルを持つ

vector<stPiece> pieces; 

そしてそのベクトルへのポインタ

stPiece *mother;

ポインタをインデックスに変換できます

vector<stPiece>::size_type i = mother - &pieces[0];
assert(i < pieces.size());

次に、インデックスをイテレータに変換します

vector<stPiece>::iterator it = pieces.begin() + i;

次に要素を消去します

pieces.erase(it);

以上です。

ただし、データ構造には、同じベクトルを指す複数の長寿命のポインターがあるようです。そのようなベクトルから要素を消去しようとすると、これらすべてのポインターがすぐに無効になります。すべてを注意深く行えば、理論的にはそれらの有効性を「復元」することは可能ですが、これは主要なPITAになります。

「子のピースがすべて削除されると仮定して」とはどういう意味かわかりません。

于 2010-01-14T08:01:29.850 に答える
1

はい、あなたは母親によって参照された部分を消去することができます。

' mother 'で参照されているピースを削除すると、そのすべての子のマザーポインターがぶら下がるようになり、これに注意する必要があります。

ベクトル内の要素のシフトについては、それを行う必要はありません。ベクトルクラスによって処理されます。

于 2010-01-14T04:55:13.173 に答える
1

簡単な答え:いいえ。

ピースは値ごとにベクトルに格納されます。したがって、ベクトルイテレータはピースへのポインタです。つまり、マザーピースへのポインターは、マザーでのベクトルのイテレーターと同じです。ベクトルイテレータは、挿入(すべてのイテレータ)および消去(消去されたイテレータを超えるすべてのイテレータ)で無効になります。つまり、メモリの場所が変更され、すべてのポインタを最新の状態に保つことはほぼ不可能になります。

動的に割り当てられたピースをベクトルに格納できます。つまり、次のようになります。

vector<stPiece*> pieces

ピースがベクターに追加/ベクターから削除されても、マザーポインターは変更されません。欠点は次のとおりです。

  • ここで、メモリを管理する必要があります(各ピースの新規/削除)
  • ピースごとにより多くのメモリを使用します(ポインタはピース単位で)
  • stPieceオブジェクトの連続した配列ではなくなったため、空間的な局所性(キャッシュ効率)が失われるため、速度が低下する可能性があります。

後者の2つのポイントは、アプリケーションで重要な場合と重要でない場合があります。

于 2010-01-14T05:42:54.330 に答える
1

あなたがコーディングしたのは、単一にリンクされたツリーです。stPiece作成と削除のセマンティクスを実装する際に邪魔になるため、オブジェクトにすべてのを含めることはおそらく望ましくありません。

motherすべての子がいなくなったら削除したいと思います。

set< stPiece * > all_pieces;

struct stPiece {
    boost::shared_ptr< stPiece > const mother;
    stPiece( boost::shared_ptr< stPiece > &in_mother )
     : mother( in_mother ) {
        all_pieces.insert( this );
    }
    ~stPiece() {
        all_pieces.erase( this );
    }
};

重要な点は、いくつかのオブジェクトを含めることと、単にそれらを反復処理できることには違いがあるということです。オブジェクトを作成および削除するための最も明白な方法を使用することがコンテナを使用していない場合、それらはおそらくコンテナに含まれるべきではありません。

于 2010-01-14T07:48:26.383 に答える