0

例外の安全性に関してアドバイスをお願いしたいと思います。特に、私は参照していますDo you (really) write exception safe code? . タイプ のオブジェクトへのポインターのコンテナーがあり、そのオブジェクトのNodeコンテナーをクリアして、オブジェクト_nodesの新しいコレクションで再初期化する場合、このコードは例外セーフでしょうか?

std::vector<Node*> nodes;

for (int i = 0; i < 10; i++)
{
    try
    {
        // New can throw an exception. We want to make sure that if an exception is thrown any allocated memory is deleted.
        std::unique_ptr<Node> node(new Node());
        Node* n = node.get();
        nodes.push_back(n);
        node.release();
    }
    catch (std::exception& exception)
    {
        // If an exception is thrown, rollback new allocations and rethrow the exception.
        for (std::vector<Node*>::iterator it = nodes.begin(); it < nodes.end(); it++)
        {
            delete *it;
        }

        nodes.clear();
        throw exception;
    }

}

_nodes.swap(nodes);

// Delete the unused (previous) objects from the swapped container.
for (std::vector<Node*>::iterator it = nodes.begin(); it < nodes.end(); it++)
{
    delete *it;
}

私はRAIIも読んでいますが、ポリモーフィズムが必要な場所でこれがどのように機能するかわかりません( http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping )。

4

1 に答える 1

1

それは必要以上に複雑です。私は次のように始めます:

std::vector<std::unique_ptr<Node>> nodes(10);    
for (auto& p : nodes)
    p.reset(new Node());

ベクトルを構築するか、Nodeスローを割り当てる場合、すべてが自動的にクリーンアップされます。

あなたが賢明で置き換えれば_nodesstd::vector<std::unique_ptr<Node>>関数の残りの部分は単純です:

_nodes.swap(nodes);

それ以外の場合は、それほど単純ではありません。

std::vector<Node*> nodes2;
nodes2.reserve(nodes.size());
for (auto p : nodes)
    nodes2.push_back(p.release());
_nodes.swap(nodes2);
for (auto p : nodes2)
    delete p;

デストラクタがスローできないと仮定すると、Nodeここでスローできる唯一のステップはreserve呼び出しであるため、オブジェクトnodesを保持しているため、そのスローがクリーンアップされunique_ptrます。その後、安全に所有権を に転送しnodes2、スワップしてからクリーンアップできます。

私もRAIIを読んでいますが、ポリモーフィズムが必要な場所でこれがどのように機能するかわかりません

上記のコードは RAII に依存しており、ポリモーフィズムは無関係です。上記のコードには、RAII タイプによって所有されていない生のポインターはありません (ただし、_nodesに変更する必要がありますstd::vector<std::unique_ptr<Node>>)。したがって、例外がスローされた場合、すべてがクリーンアップされ、例外をキャッチして手動で実行する必要はありません。掃除。

于 2014-03-16T20:24:10.310 に答える