在事先不知道维度的情况下初始化多维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));
}
上下文: 我有一个 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));
}