簡體   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