【问题标题】:C++ how to instantiate std::array inside a class constructor?C ++如何在类构造函数中实例化std :: array?
【发布时间】:2020-05-11 18:07:32
【问题描述】:

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

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

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

现在我想做同样的事情,但将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);

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

那么我该怎么做呢?

【问题讨论】:

  • 通过模板参数传递数组大小?请注意,通常编译器需要知道为C 的实例分配多少存储空间。所以sizeof(C)必须相同,不能依赖构造函数参数。

标签: c++ compile-time


【解决方案1】:

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

一个类的类型必须是“完整的”才能调用构造函数——而一个类要“完整”,它必须是完全定义的(因此,大小必须是已知的)。如此有效地,通过构造函数将其传递是不可能的——即使该值是一个真正的常量表达式。

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

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

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


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


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

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

【讨论】:

    【解决方案2】:

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

    template <int my_size>
    class C
    {
        std::array<int, my_size> data;
    }
    
    auto c = C<100>();
    

    您不能使用函数参数指定模板参数(std::array&lt;T, N&gt; 中的N)。 constexpr 在这里没有帮助。

    【讨论】:

    • std::array的参数是std::size_t不是int
    【解决方案3】:

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

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

    【讨论】:

    • 我确实知道编译时的大小。这是一个constexpr,所以它在编译时是已知的。
    • @lomawa 编译器调用构造函数的时候知道大小,但是在声明类之前编译器需要知道。编译器必须知道类布局和对象大小 - 并且不能仅通过查看您提供的类声明来知道它。事实上,如果 mysize 在 std::array&lt;int,mysize&gt; data; 行不知道,您的代码将无法编译
    猜你喜欢
    • 2016-02-16
    • 2022-01-22
    • 2018-07-08
    • 1970-01-01
    • 2016-07-05
    • 2016-05-31
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多