首页 > 解决方案 > 将 unique_ptr 添加到向量中是否可以接受这种方式?

问题描述

说我有一个盒子。它包含由 制造的事物,Box并且只有Box。事物也是不可复制的。

还有一个所有权关系,所以我想用unique_ptrs. (如果盒子消失了,一切都会随之而来。)

#include <memory>
#include <vector>

class Thing {
    friend class Box;
    public:
    ~Thing() {/* delete thing */};

    private:
    Thing() {/* construct thing */};
    Thing(const Thing& other) = delete;
    Thing& operator=(Thing&& other) = delete;
};

class Box {
    private:
    std::vector<std::unique_ptr<Thing> > contents{};

    public:
    void makeThing() {
        contents.push_back(nullptr);
        contents.back().reset(new Thing()); // I can live with the 'new' keyword here.
    }
};

我的问题是:通过推动 anullptr然后将其重置为新对象来添加向量是否不好?(除了new关键字,如果构造函数不抛出,这似乎很好?)

注意:我已经看到了克服私有构造函数和删除复制语义的替代 方法。但是我上面写的有什么危险的错误吗?

注意 2:在这里明确说明,因为它已经吸引了一些人:由于 Thing 构造函数是私有的,std::make_unique 因此无法正常工作。

标签: c++

解决方案


我会使用这个构造:

auto thing = std::unique_ptr<Thing>(new Thing());
contents.push_back(std::move(thing));

因为这更多地描述了您实际想要做的事情。您的Box对象创建一个Thing对象,将所有权传递给 a unique_ptr,然后您将其unique_ptr移至contents.

并且不要使用contents.emplace_back(new Thing());一个理由来确定它可能会泄漏。但是 - 恕我直言 - 更重要的部分是可读性和可维护性,如果你写,contents.emplace_back(new Thing());那么你需要检查是否contents.emplace_back真的声称拥有所有权(那contents真的是类型而std::vector<std::unique_ptr<Thing> >不是std::vector<Thing *>,很明显,所有权被移动了。std::move(thing)thingunique_ptr

您的解决方案的缺点是,在阅读contents.push_back(nullptr);时不清楚为什么nullptr要添加,您需要阅读下一行以了解原因。


推荐阅读