在事先不知道维度的情况下初始化多维std::vector

Initializing multi-dimensional std::vector without knowing dimensions in advance

上下文: 我有一个 class,E(将其视为有机体)和结构 H(有机体中的单个细胞)。目标是估计 E 的一些特征参数。 H 具有一些存储在多维矩阵中的属性。但是,尺寸取决于 E.

的参数

E 从输入文件中读取一组参数,声明一些 H 类型的对象,解决它们的每个问题并填充矩阵,计算似然函数,导出它,然后继续下一组参数。

我曾经做过的事情:我曾经在H的头文件中声明指向指针的指针,并推迟分配给H的构造函数的内存。这样,E 可以将参数传递给构造函数,然后再进行内存分配。我在析构函数中取消分配内存。

问题:昨天,我发现这是bad practice! So, I decided to try vectors. I have read several tutorials. At the moment, the only thing that I can think of is using push_back() as used in the question here. But, I have a feeling that this might not be the best practice (as mentioned by many, e.g., here,在方法3下)。

有数十个问题与此相关,但 none 直接回答了这个问题:如果事先不知道维度,最佳做法是什么?

任何建议都有帮助:我还有其他解决方案吗?我应该坚持使用阵列吗?

使用push_back()应该没问题,只要vector预留了合适的容量即可。

如果您对使用 push_back() 的唯一犹豫是执行重新分配时的复制开销,那么有一种直接的方法可以解决该问题。您使用 reserve() 方法来通知向量该向量最终将包含多少个元素。只要 reserve() 在使用向量之前被调用,只需要一次分配所需的数量。然后,push_back() 不会在向量被填充时发生任何重新分配。

来自您的 cited source 中的示例:

std::vector<std::vector<int>> matrix;
matrix.reserve(M);
for (int i = 0; i < M; i++)
{
    // construct a vector of ints with the given default value
    std::vector<int> v;
    v.reserve(N);
    for (int j = 0; j < N; j++) {
        v.push_back(default_value);
    }

    // push back above one-dimensional vector
    matrix.push_back(v);
}

这个特定的例子是人为设计的。正如 @kei2e 在评论中指出的那样,内部 v 变量可以在循环外部初始化一次,然后对每一行重复使用。

然而,正如@Jarod42 在评论中指出的那样,整个事情实际上可以通过 matrix:

的适当构造来完成
std::vector<std::vector<int>> matrix(M, std::vector<int>(N, default_value));

如果此初始化任务使用来自某些外部源的值填充 matrix,则可以使用 @Jarod42 的其他建议,将元素移动到位以避免复制。

std::vector<std::vector<int>> matrix;
matrix.reserve(M);
for (int i = 0; i < M; i++)
{
    std::vector<int> v;
    v.reserve(N);
    for (int j = 0; j < N; j++) {
        v.push_back(source_of_value());
    }

    matrix.push_back(std::move(v));
}