4

複数のリストになる可能性のあるオブジェクトがあります。

例えば

std::list<object*> lista = new std::list<object*>();
std::list<object*> listb = new std::list<object*>();

object* obj = new object();
lista->push_front(obj);
listb->push_front(obj);

両方のリストに同じ方法で配置されるオブジェクトが多数存在する可能性があります。スマート ポインターを使用するのは簡単なことだと思いますが、私をマゾヒストと呼んでください。

現在、私はこのテクニックを試しています:

td::list<object*>::iterator iter;
for(iter = lista->begin(); iter != lista->end(); iter++) {
    delete (*iter);
    *iter = 0;
}

std::list<object*>::iterator iterB;
for(iterB = listb->begin(); iterB != listb->end(); iterB++) {
    if(*iterB != 0) {
        delete (*iterB);
        *iter = 0;
    }
}

delete lista;
delete listb;

しかしdelete lista;、実行時に相当するもので壊れます。ポインターについてもっと賢い人が私を助けてくれることを願っています。前もって感謝します!

PS Windows 7/MinGW を実行しています。

4

5 に答える 5

3

A main problem is that you (apparently, you do not offer complete code) delete an object twice: once when iterating through list A, and once when iterating through list B.

There are three main solutions:

  • Use a ref-counting smart pointer like std::shared_ptr.
    Recommended. Your statement that you do not want to use a smart pointer seems to be made out of ignorance rather than some silly-manager's requirement.

  • Keep the nodes also in a primary list:
    delete a node only when you know that the only list it's still in, is the primary list.

  • Implement a reference count yourself:
    The easiest is again to use an existing library solution such as boost::intrusive_ptr, but all you have to do is to meticulously maintain a reference count in each node. delete when the reference count goes down to 0.

A fourth possibility is to use a garbage collector such as the Boehm collector, but then the code needs to be structured to support it. Or at least that's my impression. And it may be difficult to get help with that, since very few C++ programmers use that approach (which indicates that it's not entirely free of problems).

于 2012-12-29T04:15:36.087 に答える
1

shared_ptrでマスター リストを使用または作成しunique_ptrます。

それができない場合は、ポインターを所有するマスター リストを用意し、クリア後にマスター リストから削除しますが、他のすべてのリストは削除しません。

それができない場合は、リストから直接削除しないでください。代わりにinsert、必要なポインターを にstd::set移動し、削除する前に他のリストからそれらを削除するか (反復してセット内で検索する)、または破棄するすべてのポインターを蓄積してからセットから一括削除します。

これは、段落ごとの吸い込みの大まかな順序です。

于 2012-12-29T04:10:35.003 に答える
0

なぜあなたが本当にshared_ptrを使いたくないのか分かりません。わかりました自分に合わせてください。ローカルに shared_ptr を作成するのはどうですか? そうでない場合は、両方のリストを 1 つのマスター リストにロードします。2 つのサブリストをクリアし、マスター リストをクリアするだけでなく、マスター リストの各要素を削除します。

于 2012-12-29T03:54:41.570 に答える
0

カウンター フィールドを に追加しますobject。デフォルトは 0 に初期化されます。リストに追加すると +1 が追加されます。リストから削除すると -1。の場合counter==0は、削除しobjectます。

これは のようにスレッドセーフではありませんshared_ptrが、同じ理由ではるかに高速になる可能性があります。

于 2012-12-29T05:38:36.460 に答える
0

ラインで

if(*iterB != 0) {

*iterB が 0 になることはありません。したがって、二重に削除しています。

于 2012-12-29T05:11:29.513 に答える