std::array 没有默认构造函数的对象的初始化?

std::array initialization, for objects without a default ctor?

我在一个内存受限的系统上工作,其中 new/malloc 调用被包装以在构建时失败。不幸的是,std::vector 不是一个可接受的解决方案。

我有一个 class 的 std::array 成员,其大小在编译时已知,但可能因特定目标(例如来自配置文件)而异,所以我可以访问类似constexpr size_t len = Config::ArrSize。我希望我的 class 包含 std::array 个对象,但这些对象没有默认构造函数。我更愿意避免两步初始化(例如,实现一个无意义的默认构造函数,然后稍后将实际值传递给它们)。我也知道编译时的所有构造函数值!我只是找不到一种干净的方式来传达这一点,因为 length 可能因特定目标而异,但对于任何 given garget 都是已知的。

有没有办法清楚地传达这一点?例如我想要类似于

的东西
#include Config.h

constexpr size_t arr_size = Config::ArrSize;
constexpr size_t ctor_arg = Config::Arg;

class Foo {
  public:
  // line which doesn't work but demonstrates what I'd like
  Foo() : fooArr {Bar(ctor_arg)} {}
  private:
  std::array<Bar, arr_size> fooArr;

};

它们都将以相同的方式初始化,并且在编译时具有已知的大小。由于缺少默认构造函数,它们必须在初始化时构造。类似于 std::fill 但在初始化时可用。是的,我可以用指针将它推迟一点,直到 ctor 主体,但恕我直言,这很丑陋。我该怎么做?

Bar 没有 constexper 构造函数,但也许这会有所帮助?

你可以这样做:

class Bar
{
public:
    Bar(someClass obj) { /*...*/ }
};

class Foo
{
public:
    template<class... T>
    Foo(T... obj) : fooArr {Bar(obj)...} {}
private:
    std::array<Bar, arr_size> fooArr;
}

虽然我不知道这是否是最好的方法。

选项 1:使用命名构造函数惯用语

我们将编写一个 named constructor idiomarray_repeat(),它采用单个值并在 compile-time 处生成一个包含所有值的数组。然后你可以写:

class Foo {
public:
  Foo() : fooArr {array_repeat<arr_size>(Bar(ctor_arg))} {}
private:
  std::array<Bar, arr_size> fooArr;
};

我已将实现拆分为单独的问答,here on SO

选项 2:使用带有自定义分配器的向量

std::vector has 一个额外的模板参数 - 分配器 class。默认值是使用 new[]delete[] 的分配器。但是 - 你可以有一个分配器占用堆栈上的固定缓冲区(或任何地方),并仍然使用可调整大小的 std::vector 。这将使您无需 pre-construct 虚拟值。

您可以使用大括号初始化 std::array<int,4> a = {1,2,3,4};...也许您可以编写一个模板函数来初始化它而不直接编写初始化列表,但我不确定如何。

一般来说,当类型不可默认构造时,我不建议使用 std::array。您可以使用像 boost::small_vector 这样具有静态容量和动态大小的类型。