我想要一个大容器(特别是 a std::array),其大小我在编译时知道,但我可以从构造函数中指定。
我已经能够完成第一部分:即 std::array ,其大小在编译时指定。示意图:
// hpp
constexpr int my_size = 100;
class C
{
std::array<int, my_size> data;
}
// main
c = C()
Run Code Online (Sandbox Code Playgroud)
现在我想做同样的事情,但是传递std::array到类构造函数中,可能作为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);
Run Code Online (Sandbox Code Playgroud)
显然这是错误的,因为mysize它是在构造函数中传递的,但mysize也是在声明时必须知道的类型的一部分。
那么我该怎么做呢?
更改范围(大小)std::array将更改包含它的对象的大小 - 因为数组元素是连续存储在对象中而不是间接存储(例如通过指针)。
类的类型必须是“完整的”,以便调用构造函数——并且对于“完整的”类,它必须是完全定义的(因此,大小必须是已知的)。因此,实际上,通过构造函数传递它是不可能的——即使该值是一个真正的常量表达式。
完成您尝试使用的操作的唯一方法是 根据数组的大小std::array创建classa 。template模板允许编译器根据模板参数输入生成不同的类,因此每个实例化可以具有不同的大小:
template <std::size_t N>
class C {
...
std::array<int, N> data;
};
Run Code Online (Sandbox Code Playgroud)
请注意,在执行此操作时,您对所有关联功能的定义现在可能会卡在标头中 - 因为整个定义必须可见才能实例化正常工作(这通常将它们限制在标头中)。此外,模板可能会通过为每个实例化复制生成的代码而导致代码膨胀。因此,如果您预计该模板会出现大量实例,则需要考虑这一点。
如果您想根据运行时输入使用这种类型,那么使用它可能会更简单std::vector。
class C {
C(int mysize) : data{mysize}{}
std::vector<int> data;
};
Run Code Online (Sandbox Code Playgroud)
但是,里面的元素std::vector不会直接存储在 中C,而是间接存储在分配的内存中(可能在堆上)