为双向量保留空间

Posted

技术标签:

【中文标题】为双向量保留空间【英文标题】:Reserving space for a double vector 【发布时间】:2019-09-16 11:28:39 【问题描述】:

假设T 是一个类型,我想创建一个vector<vector<T>>。我知道最终的大小将是m x n,其中mn 是运行时常量。 (如果它们是编译时常量,我会使用std::array<std::array<T, n>, m>。)假设在我认真地继续我的程序之前,我有三个选择来处理我的双向量:

选项 1

std::vector<std::vector<T>> dbl_vect(m);
for (auto & v : dbl_vect)
    v.reserve(n);

选项 2

std::vector<std::vector<T>> dbl_vect;
dbl_vect.reserve(m);

选项 3

std::vector<std::vector<T>> dbl_vect;

假设我不担心向量重新分配导致迭代器和引用失效,因此我们可以将其从决策过程中移除。

当然,后面的代码会有所不同,因为#1 创建了 dbl_vector 的(空)行,所以我们必须访问这些行而不是推回更多行。

选项#2 似乎没什么用,因为它不知道为每一行保留多少空间。

选项 #1 要求我通过 m 空向量的线性传递并手动调整它们的大小,但它会阻止重新分配。如果T 相当大,我相信这几乎肯定会更好,因为它可以防止复制/移动。

问题:假设T = char(或选择您最喜欢的 POD 类型)。在什么情况下我应该对选项1和3无动于衷,甚至更喜欢#3?这主要是因为char 的大小相对较小,还是因为编译器将(不)默认初始化char 的方式?如果T 更大,可能是用户定义的,我应该在什么时候开始关心(双向量的大小或T 的大小)?

Here 提出了一个有点类似的问题,关于一个向量和T=int

【问题讨论】:

你想通过使用reserve()而不是仅仅创建你想要的vectors来解决什么问题? @SidS 我很清楚,你的意思是一个接一个地创建它们并在我去的时候打电话给push_back?这可能意味着重新分配,这可能值得避免。 @EricAuld:不,他的意思是从迭代器创建它们,以便它们从一开始就具有值。 @MooingDuck 哦。我假设我的代码比这更复杂,所以我不提前知道它们的值是什么。 (想象一下我正在编写代码以将所有可能的分区返回给我的情况......你明白了) #4 std::vector&lt;T&gt; vec; vec.reserve(m * n); 【参考方案1】:

如果您知道内部大小为m,一种可能性是创建std::vector&lt;S&gt;,其中S 是您的自定义类型,代表std::vector&lt;T&gt;,但它知道它将有多少条目。建议使用类似的解决方案 here(除了 m 是编译时常量)。

【讨论】:

【参考方案2】:

#3 只是默认初始化向量。没有任何收获,因为包含向量的容量为零。动态分配内存很慢,所以为了尽量减少这种情况,我总是选择 #1 或其变体。

【讨论】:

我认为这不是真的。它创建一个空的外部向量并且没有内部向量。 (选项 3 不会告诉它要创建多少个内部向量。)与实际创建 (empty, m) 内部向量的 1 相反,它最终将有 n 个条目。不是说你在大局中错了,但除非我错了,否则你在初始化方面是错的。 是的。包含向量没有元素,我应该更清楚地表达出来 "...依次将值初始化或默认初始化...所有包含的向量。"这就是我所说的选项 3 不会做的事情。不会创建任何包含的向量,只会创建单个包含向量。

以上是关于为双向量保留空间的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用额外空间的情况下检查双向链表是不是为回文?

为 QScrollArea 保留空间

为啥要为局部变量保留堆栈空间?

为滚动条保留的空间截断文本

Python:告诉 X 为应用程序保留屏幕空间

elasticsearch安装插件:无法为对象堆保留足够的空间