【问题标题】:Initializing multi-dimensional std::vector without knowing dimensions in advance在事先不知道维度的情况下初始化多维 std::vector
【发布时间】:2021-09-16 23:04:36
【问题描述】:

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

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

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

问题:昨天,我意识到这是bad practice!所以,我决定尝试向量。我已经阅读了几个教程。目前,我唯一能想到的就是使用问题here 中使用的 push_back()。但是,我感觉这可能不是最佳实践(正如许多人提到的,例如,here,在方法 3 下)。

与此相关的问题有几十个,但没有一个直接回答这个问题:如果事先不知道尺寸,最好的做法是什么?

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

【问题讨论】:

  • 有许多不同的方法来处理vector 维度,如link you provided 中所述。它们都非常好,但适用于不同的用例。那么你对他们的实际问题是什么?无论如何,只要你正确地遵循Rule of 3/5/0,使用指向指针(甚至只是指针)并没有错,大多数人一开始不会这样做。
  • 我在析构函数中解除了内存分配。 -- 如果在你最初分配的时候任何这些分配在中间的某个地方失败了,你是如何处理这个问题的?我在问,因为指针到指针的东西总是有一些人们没有想到的重要细节——如果内存分配失败。
  • 如果事先不知道尺寸,最好的做法是什么? -- resize()push_back()emplace_back()insert()(我忘记了吗? ?)。那么在这些中,哪一个适合您想要完成的目标?
  • 我不知道,@PaulMcKenzie。可能我所做的一个原因被认为是不好的做法。 (这也部分与 Remy 的观点有关:看来我没有遵循三定律——例如,我没有处理分配失败。)
  • @PaulMcKenzie,他们都有效。但是,我不确定哪个最有效。

标签: c++ arrays stdvector push-back


【解决方案1】:

使用push_back()应该没问题,只要向量保留了适当的容量。

如果您对使用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));
}

【讨论】:

  • matrix.push_back(std::move(v)); 避免额外复制,或直接std::vector&lt;std::vector&lt;int&gt;&gt; matrix(M, std::vector&lt;int&gt;(N, default_value));
  • 这很有意义;谢谢!问题:执行一次内部循环(v.push_back())不是更有效吗?两个单独的循环而不是嵌套的循环?
  • @Jarod42 谢谢,答案已更新。
  • @kei2e 这是一个很好的观点,但 Jarod42 的建议在这种情况下更直接。教程的人为示例就是这样。
  • @kei2e BTW,考虑使用tour
猜你喜欢
  • 2013-07-13
  • 1970-01-01
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 2020-10-16
  • 2016-05-12
  • 2018-03-26
  • 1970-01-01
相关资源
最近更新 更多