如何创建指向默认构造对象的唯一指针向量

How to create a vector of unique pointers pointing at default constructed objects

有没有办法创建包含 Nstd::unique_ptr<T> 的向量? GCC v11.2 显示了巨大而神秘的错误消息,因此我无法检测到问题。

这是我尝试做的 MRE:

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


// a dummy struct
struct Foo
{
    int m_value;
};


int main( )
{
    constexpr auto rowCount { 10uz };
    constexpr auto colCount { 20uz };

    // a 1D vector of pointers, does not compile
    std::vector< std::unique_ptr<Foo> > vec_1D( colCount, std::make_unique<Foo>( ) );

    for ( const auto& ptr : vec_1D )
    {
        std::cout << "Address: " << ptr << " --- value: " << ptr->m_value << '\n';
    }

    // a 2D vector of pointers, does not compile
    std::vector< std::vector< std::unique_ptr<Foo> > >
        matrix( rowCount, std::vector< std::unique_ptr<Foo> >( colCount, std::make_unique<Foo>( ) ) );

}

我想我在这里遗漏了一些关于 std::unique_ptr 的重要信息。这个错误是因为 unique_ptr 不是可复制构造的吗?

如果上述方法不可行,那么有什么替代方法?

行:

std::vector< std::unique_ptr<Foo> > vec_1D( colCount, std::make_unique<Foo>( ) );

使用以下向量构造函数:

     vector( size_type count,
             const T& value,
             const Allocator& alloc = Allocator());

它接收给定值并将其复制到向量的每个元素。来自 cppreference:

  1. Constructs the container with count copies of elements with value value.

因此您正在调用 std::make_unique<Foo>(),从该调用中获取 std::unique_ptr<Foo>&&,并将其传递给 std::vector 的构造函数,以便它进行复制。 问题是唯一指针不可复制


你可以:

  • 创建具有给定大小的向量,并且
  • 对于向量中的每个元素,
    • 创建一个唯一的指针(一次一个),并且
    • 移动分配指向向量元素的唯一指针。

下面的示例使用 std::generate 来填充向量。请注意,生成器函数正在返回一个 std::unique_ptr<Foo>&&,它可以移动分配给每个向量的元素。

[Demo]

#include <algorithm>  // generate
#include <iostream>  // cout
#include <memory>
#include <vector>

// a dummy struct
struct Foo
{
    Foo() : m_value{value++} {}
    static inline int value{};
    int m_value{};
};

int main( )
{
    const size_t count{ 20 };
    std::vector<std::unique_ptr<Foo>> v(count);
    std::generate(v.begin(), v.end(), []() { return std::make_unique<Foo>(); });
    for (auto&& up : v) { std::cout << up->m_value << " "; }
}

// Outputs
//
//   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19