繁体   English   中英

在智能指针容器中添加项目

[英]Add an item in a container of smart pointers

在智能指针容器中添加项目的几种方法。 我想知道你会选择哪种方式。

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给出了很多好处。 在以下常见情况中。 如何使用方式2或3轻松完成? 用户使用对话框生成新的派生项。 它被放在std::unique_ptr<DerivedItem> item 单击“确定”按钮时,会将其添加到容器中。 如果添加失败,请返回对话框进行编辑。

我投票支持:

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

原因:

  1. 从函数签名中可以清楚地看出,客户端需要将对象的所有权传递给MyContainer 如果您选择选项1,则仍然不清楚客户端是否应该自己delete对象,或者即使它们应该传递动态分配的对象。

  2. 如果客户端已经拥有由命名为std::unique_ptr管理的对象,则必须使用std::move显式转移所有权。 他们不会意外失去所有权。 选项3没有明确表示它将取得所有权。

  3. 当我们有std::make_unique (N3588)时 ,添加元素的方法将是:

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

    这避免了在某些情况下使用new并改善了异常安全性。

  4. 您为派生对象提供的问题并不是真正的问题。 如果你做错了,你会得到一个编译时错误。

  5. 如果界面更改为使用不同类型的智能指针,则客户端将需要知道。 他们不想继续传递认为他们通过所有权的对象,如果实际上他们正在共享它。 他们特别想知道相反的情况。

不幸的是,第一种方式严重危及类型安全 - 你已经指出我们自己处于劣势。 我认为这些担忧超越了这种方法可能带来的任何好处。

特别是,在编译时捕获使用派生对象时第二种方法的潜在错误,因此它很烦人,但是很安全

我同意你的评估,这种用法泄露了实现细节,但根据我的经验,这种泄漏是不可避免的 - 我同意sfrabbit这实际上是这个类的用户需要了解的细节。

将此视为工具箱中的另一个工具:

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

这结合了方式2和方式3的优点。即它只接受rvalue 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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM