【问题标题】:unique_ptr to nullptr is uncopyableunique_ptr 到 nullptr 是不可复制的
【发布时间】:2018-10-20 22:42:58
【问题描述】:

看起来像将 unique_ptr 的嵌套向量创建为空抛出 试图引用已删除的函数。我相信这是因为它试图复制向量 unique_ptr(nullptr) 的并且 unique_ptr(nullptr) 是不可复制的。

#include <memory>
#include <vector>
struct Foo {
};
int main() {
    std::vector<std::vector<std::unique_ptr<Foo>>> foo(5, std::vector<std::unique_ptr<Foo>>(5));
}

https://onlinegdb.com/SkvGkVYoQ

我不确定如何继续。我只需要一个 nullptr 的多维数组,如果它们是唯一的,那就太好了 - 除了解决这个问题之外,不需要 shared_ptr。

【问题讨论】:

  • 它与 nullptr 无关——unique_ptr 本身是不可复制的,正如它的名字所暗示的那样。
  • 对。那么我将如何通过定义默认大小来创建一个 unique_ptr 的多维数组呢?
  • 不要使用 std::vector 的 copy-from-element ctor 制作第一个维度,然后使用 ranged for 调整每个向量的内部维度。
  • 你为什么使用vector&lt;unique_ptr&lt;Foo&gt;&gt; 而不仅仅是vector&lt;Foo&gt;
  • 我想在未来某个时间点将 Foo 的所有权分配给向量 vector&lt;unique_ptr&lt;Foo&gt;&gt; foo; foo.at(2) = std::make_unique&lt;Foo&gt;();。这就是为什么它们现在是 nullptr 的。

标签: c++ vector null unique-ptr


【解决方案1】:

std::unique_ptr 根本不可复制。这与nullptr 无关。最简单的解决方法是只使用一维数组并映射维度。

然后你可以这样做:

for (std::size_t j = 0; i < 5; ++j) {
    for (std::size_t i = 0; i < 5; ++i) {
        std::size_t index = j*5+i;
        foo.emplace_back(std::make_unique<Foo>());
    }
}

(您可以使用嵌套的std::vectors 应用类似的模式,但这样在缓存位置等方面可能会更好。)

【讨论】:

  • 确实,这不仅更简单,而且速度更快(只有一个间接,更少的分配......)并且比嵌套的std::vector 具有更小的内存占用。嵌套的std::vector 只有在你真的有一个不可预测的、不同大小的向量时才应该使用。
  • 同意;但是,我不能使用std::array&lt;Foo, n&gt;,因为我不知道编译时的大小:n 是通过构造函数传递的。
【解决方案2】:

如果由于向量中每个嵌套向量元素的大小不同而需要嵌套多个向量,则可以使用std::move 将唯一的ptr 从一个向量移动到另一个向量。

    std::vector<std::unique_ptr<Foo>> container1;
    std::vector<std::unique_ptr<Foo>> container2;
    for (int i = 0; i < 10; ++i)
    {
        container1.emplace_back(std::make_unique<Foo>());
    }

    for (int i = 0; i < 2; ++i)
    {
        container2.emplace_back(std::make_unique<Foo>());
    }

    std::vector<std::vector<std::unique_ptr<Foo>>> containers;
    containers.emplace_back(std::move(container1));
    containers.emplace_back(std::move(container2));

    return 0;

映射是最快的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2014-06-30
    • 2019-02-06
    • 2014-07-26
    • 2018-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多