Add item to container with smart pointers

Several ways to add an item to a smart pointer container. I wonder what path you will take.

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>

};

I personally go on the Way 1. Any additional advantages for the Way 2 and 3 or shortcomings of the Way 1 on which I should go 2 or 3?

sftrabbit gives a lot of good points. In the following general case. How to use Path 2 or 3 to make this easy? The user uses the dialog to create a new derived element. He is placed in std::unique_ptr<DerivedItem> item. When you click OK, it is added to the container. If adding failed, return to the dialog box for editing.

+5
source share
3 answers

I vote for:

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

:

  • , MyContainer. 1 , , delete , .

  • std::move, , std::unique_ptr. . 3 , .

  • std::make_unique (N3588), :

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

    new .

  • , , . , .

  • , , . , , , . , .

+6

, - , . , , .

, , , !

, , - sfrabbit , , .

+2

Consider this as another tool in the toolbar:

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

This combines the advantages of path 2 and path 3. Ie it will only accept the rvalue value unique_ptr(for example, 2), but if there is some error when adding it to the container, it can save ownership as 3. Something like: can be used:

void
foo(MyContainer& c)
{
    std::unique_ptr<Item> p = get_Item();
    try
    {
        c.Add(std::move(p));
    }
    catch (...)
    {
        log_error_wtih(*p);
    }
}
+1
source

All Articles