簡體   English   中英

高效優雅地返回emplaced unique_ptr

[英]Efficiently and elegantly returning emplaced unique_ptr

我發現( 感謝StackOverflow注釋 )我的代碼中存在安全漏洞:

std::vector<std::unique_ptr<Item>> items;

template<class... TS> Item& create(TS&&... mArgs)
{
    auto item(new Item(std::forward<TS>(mArgs)...);
    items.emplace_back(item); // Possible exception and memory leak
    return *item;
}

基本上,如果emplace_back拋出,則使用raw new分配Item可能會泄漏內存。

解決方案永遠不會使用原始new ,而是在方法體中使用std::unique_ptr

std::vector<std::unique_ptr<Item>> items;

template<class... TS> Item& create(TS&&... mArgs)
{
    auto item(std::make_unique<Item>(std::forward<TS>(mArgs)...);
    items.emplace_back(std::move(item));
    return *item; // `item` was moved, this is invalid!
}

如您所見,返回item無效,因為我必須使用std::move移動item以將其放入items容器中。

我想不出一個需要將item地址存儲在附加變量中的解決方案。 然而,原始(錯誤)解決方案非常簡潔易讀。

是否有更優雅的方式返回一個std::unique_ptr被移動以便放置在容器中?

你可以寫:

template<class... TS>
Item& create(TS&&... mArgs)
{
    items.emplace_back(std::make_unique<Item>(std::forward<TS>(mArgs)...));
    return *items.back();
}

在emplace之前緩存引用是更普遍適用的選項(例如,對於非向量容器):

template<class... TS> Item& create(TS&&... mArgs)
{
    auto item = std::make_unique<Item>(std::forward<TS>(mArgs)...);
    auto& foo = *item;
    items.emplace_back(std::move(item));
    return foo; // This *is* valid.
}

你的問題被標記為C ++ 11,其他答案表明make_unique沒有提到它是C ++ 14的特性。 我相信這種C ++ 11方法也可以解決泄漏問題。

#include <vector>
#include <memory>
#include <utility>
#include <iostream>

struct Item
{
   int a, b;
   Item(int aa, int bb) : a{aa}, b{bb} { }
};

static std::vector<std::unique_ptr<Item>> items;

template <class... Ts> Item& create(Ts&&... args)
{
    items.emplace_back(std::unique_ptr<Item>{new Item(std::forward<Ts>(args)...)});
    return *items.back();
}

int main()
{
    Item& x = create(1, 2);
    std::cout << "( " << x.a << ", " << x.b << " )" << std::endl;
}

這應該是安全的,因為在構造unique_ptr<Item>之前無法調用emplace_back() ,因此即使emplace_back()拋出,您的Item也已由unique_ptr管理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM