C++ 如何在 class 构造函数中实例化 std::array?

C++ how to instantiate std::array inside a class constructor?

我想要一个大容器(特别是 std::array),其大小我在编译时知道,但我可以从构造函数中指定。

我已经能够完成第一部分:即 std::array,其大小在编译时指定。示意图:

// hpp
constexpr int my_size = 100;
class C
{
    std::array<int, my_size> data;
}
// main
c = C()

现在我想做同样的事情,但是将 std::array 传递给 class 构造函数,可能作为 constexpr:

// hpp
class C
{
    std::array<int, mysize> data;
    C(constexpr int mysize);
}
// cpp
C::C(constexpr int mysize)
{
    data = std::array<int, mysize>
}
// main
constexpr int mysize = 100;
c = C(mysize);

显然这是错误的,因为 mysize 是在构造函数中传递的,但是 mysize 也是在声明时必须知道的类型的一部分。

那我该怎么做呢?

std::array 适用于编译时已知大小的数组。在您的情况下,您需要一个大小在运行时设置的数组。你需要 std::vector.

class C
{
    std::vector<int> data;
    C(constexpr size_t mysize) : data(mysize) {}
}

C 需要制作一个基于 int 的模板 class 并相应地构造:

template <int my_size>
class C
{
    std::array<int, my_size> data;
}

auto c = C<100>();

不能用函数参数指定模板参数(N in std::array<T, N>)。 constexpr 在这里没有帮助。

更改 std::array 的范围(大小)将更改包含它的 object 的大小——因为数组元素连续存储在 object 中而不是间接存储(例如通过指针)。

A class' 类型必须是 "complete" 才能调用构造函数——而对于 class 是 "complete",它必须完全已定义(因此,大小必须已知)。如此有效,通过构造函数传递它是不可能的——即使该值是一个真正的常量表达式。

使用 std::array 完成您正在尝试做的事情的唯一方法是使 class 成为 template 尺寸的阵列。模板允许编译器根据模板参数输入生成不同的 classes,因此每个实例化可以有不同的大小:

template <std::size_t N>
class C {
    ...
    std::array<int, N> data;
};

请注意,在执行此操作时,您对所有相关功能的定义现在可能会卡在 header 中——因为整个定义必须可见才能使实例化正常工作(这通常将它们限制为headers)。此外,模板可以通过为每个实例复制生成的代码来导致 code-bloat;因此,如果您预计此模板有很多实例化,则需要考虑这一点。


如果您想基于运行时输入使用此类型,使用 std::vector 可能会更简单。


class C {
    C(int mysize) : data{mysize}{}
    std::vector<int> data;
};

但是,std::vector 中的元素不会直接存储在 C 中,而是会间接存储在分配的内存中(可能在堆上)