5

スマート ポインターのコンテナーに項目を追加するいくつかの方法。あなたがどの道を行くのか気になります。

class MyContainer
{
private:
    std::vector<std::unique_ptr<Item>> mItems;

public:
    bool Add(Item* item);
    // This is Way 1
    //
    // Advantages: 
    // - Easy to add derived items, such as Add(new DerivedItem);
    // - No interface change if smart pointer type changes to such as shared_ptr;
    //
    // Disadvantages:
    // - Don't explicitly show the item to add must be allocated on heap;
    // - If failed to add, user has to delete the item.

    bool Add(std::unique_ptr<Item> item);
    // This is Way 2
    // Disadvantages and advantages are reversed from Way 1.
    // Such as to add derived item, Add(std::unique_ptr<Item>(new DerivedItem));
    //                                                    |
    //                               easy to write DerivedItem here for an error

    bool Add(std::unique_ptr<Item>& item);
    // This is Way 3
    // Similar to Way 2, but when failed to add, item still exist if it is a 
    // reference of outer unique_ptr<Item>

};

個人的には方法 1 を選択します。方法 2 と方法 3 の利点または方法 1 の欠点で、方法 2 または方法 3 を選択する必要があるものはありますか?

sftrabbit には多くの良い点があります。次の一般的な場合。Way 2または3を使用して簡単に行う方法は?ユーザーは、ダイアログを使用して新しい派生アイテムを生成します。装着されていstd::unique_ptr<DerivedItem> itemます。「OK」ボタンをクリックすると、コンテナに追加されます。追加に失敗した場合は、編集のためにダイアログに戻ります。

4

3 に答える 3

5

私は以下に投票します:

bool Add(std::unique_ptr<Item> item);

理由:

  1. クライアントがオブジェクトの所有権を に渡す必要があることは、関数のシグネチャから明らかMyContainerです。代わりにオプション 1 を選択した場合、クライアントがdeleteオブジェクト自体を必要とするかどうか、または動的に割り当てられたオブジェクトを渡す必要があるかどうかはまだ明確ではありません。

  2. std::moveクライアントは、名前付き によって管理されているオブジェクトをすでに持っている場合、明示的に所有権を譲渡する必要がありますstd::unique_ptr。誤って所有権を失うことはありません。オプション 3 は、所有権を取得することを明確に表現していません。

  3. std::make_unique(N3588)がある場合、要素を追加する方法は次のようになります。

    container.Add(std::make_unique<Item>());
    

    これにより、状況によっては例外の使用が回避newされ、安全性が向上します。

  4. 派生オブジェクトに与えた問題は、実際には問題ではありません。正しく実行しないと、コンパイル時にエラーが発生します。

  5. インターフェイスが別の種類のスマート ポインターを使用するように変更された場合、クライアントはそれを知りたがります。実際に所有権を共有している場合、所有権を譲渡していると考えてオブジェクトを渡し続けたくありません。彼らは、逆のことが起こるかどうかを特に知りたがるでしょう。

于 2013-03-21T14:11:56.237 に答える
2

残念ながら、最初の方法は型の安全性を著しく損なうものです。これらの懸念は、この方法が持つ可能性のある利点よりも優先されていると思います.

特に、派生オブジェクトを使用する場合の 2 番目のメソッドの潜在的なエラーは、コンパイル時にキャッチされるため、面倒ですが安全です。

この使用法により実装の詳細が漏洩するというあなたの評価に同意しますが、私の経験では、そのような漏洩は避けられません。これは実際にはクラスのユーザーが知る必要がある詳細であるという sfrabbit に同意します。

于 2013-03-21T14:18:26.547 に答える
1

これをツールボックスの別のツールと考えてください。

bool Add(std::unique_ptr<Item>&& item);

これは、方法 2 と方法 3 の利点を組み合わせたものです。つまり、右辺値unique_ptr(2 など) のみを受け入れますが、コンテナーへの追加に失敗した場合は、3 のように所有権を保持できます。次のように使用できます。

void
foo(MyContainer& c)
{
    std::unique_ptr<Item> p = get_Item();
    try
    {
        c.Add(std::move(p));
    }
    catch (...)
    {
        log_error_wtih(*p);
    }
}
于 2013-03-22T14:27:34.437 に答える