1

次のようなユーザー定義クラスがあります。

class Test {
public:
    bool opeatator== (const Test& rhs) const {
        return this->value_ == rhs.value_;
    }
    int value_;
};

このポインターを std::list で次のように保存しました。

std::list<Test*> tests_;
tests_.push_back(new Test());

次に、次のようにリストからノードを削除しようとしました:

Test remove_key(1);
tests_.remove_if([remove_key](const Test* p) { return remove_key == *p; });

value_ が 1 のすべてのノードを削除しますが、remove_if は ::operator delete() を呼び出すため、リスト内のオブジェクトは削除されます。私が知っているように、remove_ifはリストから削除するだけでオブジェクトを削除しませんが、デバッグすると、リストはTestクラスのデストラクタを呼び出し、オブジェクトを削除します::operator delete(_Ptr). 何が間違っていますか?

(以下のコードは、Visual Studio 2013 での STL リスト remove_if コールスタック (逆順) です。)

リスト

remove_if(_Pr1 _Pred) {
    for (iterator _First = begin(); _First != end(); )
        if (_Pred(*_First))
            _First = erase(_First);
        else
            ++First;
}

iterator erase(const_iterator _Where) {
    _Nodeptr _Pnode = _Unlinknode(_Where++);
    this->_Freenode(_Pnode);
    return (_Makie_iter(_Where));
}

void _Freenode(_Nodeptr _Pnode) {
    this->_Getal().deallocate(_Pnode, 1);
}

void deallocate(pointer _Ptr, size_type _Count) {
    _Mybase::deallocate(_Ptr, _Count);
}

void deallocate(pointer _Ptr, size_type) {
    ::operator delete(_Ptr);
}
4

2 に答える 2

2

しかし、デバッグすると、 Test クラスのリスト呼び出しデストラクタ

いいえ、そうではありません。むしろ、デストラクタが呼び出される理由は

  1. スコープ変数を作成しました。この変数remove_keyのデストラクタは、スコープ アウトされるときに自動的に呼び出されます。
  2. ラムダはremove_key値によってキャプチャされるため、スタックがラムダから巻き戻されると、のデストラクタremove_keyが呼び出されます。

別のコンテキストでは、強調表示したコードは、リンク リストのノードを削除するためのものであり、Test オブジェクトを削除するためのものではありません。

そう

void deallocate(pointer _Ptr, size_type) {
    ::operator delete(_Ptr);
}

Test へのポインタを格納するリンク リストのノードを削除しました。

于 2015-04-06T11:05:05.597 に答える
0

オブジェクト自体ではなく、リストのノードの割り当てを解除します。

                Node
              +--------+    +------+
iterator -->  | Test* -+--> | Test |
              +--------+    +------+

Testノードを削除すると到達できなくなります。

動的割り当てを使用する特定の理由がある場合は、使用することをお勧めしますstd::shared_ptr<Test>

于 2015-04-06T11:00:26.130 に答える