向量的向量占用的内存
Posted
技术标签:
【中文标题】向量的向量占用的内存【英文标题】:Memory taken by a vector of vectors 【发布时间】:2020-02-26 18:41:40 【问题描述】:vvint1
和vvint2
在内存中的预期差异(如果有)是什么?
每次push_back
发生时是否将vitest1
复制到新的内存位置?
每次push_back
发生时是否将vitest2
复制到新的内存位置?
typedef vector<int> vint_t;
typedef vector<vint_t> vvint_t;
size_t nvec = 2;
size_t nvvec = 3;
vvint_t vvint1(nvvec), vvint2(nvvec);
vint_t vitest2(nvec, 1);
for ( j = 0; j < nvvec; j++ )
vint_t vitest1(nvec, 2);
vvint1.push_back(vitest1);
vvint2.push_back(vitest2);
【问题讨论】:
我认为您可能需要修改您的问题,看起来可能是拼写错误;它目前要求区分“vvint1 和 vvint1”。这与香蕉和香蕉的区别是一样的。vvint1
和 vvint2
将是相同的。每次使用push_pack
时,两者都会复制向量。 FWIW,二维向量不是你想要的。与int**
一样,std::vector<std::vector<int>>
缺少行之间的数据局部性。缺乏连续性会影响性能。相反,您应该做的是使用类模拟 sd 结构,并使用数学将所有数据存储在 1d 向量中,以将 2d 索引转换为 1d 索引。
无关:迟早会有人混淆vint_t
和vvint_t
,因为名字很相似,而且名字很相似,很难被发现。跨度>
@Tommy - 已修复(尽管我的意思很明显)。谢谢。
vvint_t vvint1(nvvec), vvint2(nvvec);
aaaaaaaahhhh 代码太难读了。
【参考方案1】:
vvint1
和 vvint2
最初都是使用 nvvec = 3
默认构造的成员(即 int 的空向量)创建的。
push_back
总是复制或移动,但在这种情况下,您没有提供右值引用,因此您将获得副本。查看std::move
了解更多信息。
您将相同数量的东西推送到两个向量。因此,vvint1
和 vvint2
最终将具有相同的大小。
【讨论】:
【参考方案2】:vvint1
和 vvint2
内存要求为:
-
(在堆栈上,在示例中)
sizeof(vector<vector<int>>)
用于对象本身,这是相同的(vector
通常是 2-3 个指针,无论内部类型如何);
(在堆上)2 * nvvec * sizeof(vector<int>)
用于内容(nvvec
最初和nvvec
push_back
-ed 在循环中);同样,vvint1
和 vvint2
也是如此;
(在堆上)存储在这些向量中的每个向量的内容。由于向量不共享内存,并且您按值存储它们,nvec * nnvec * sizeof(int)
。还是一样。
所以总体要求是一样的:
sizeof(vector<vector<int>>) + nvvec * sizeof(vector<int>) + nvec * nnvec * sizeof(int)
普通的vector<int>
会占用更少的空间,因为第 2 项不适用。但更重要的是,在vvint_t
中,内部向量可能有不同的长度,调整任何内部向量的大小不会影响其他向量。但这增加了复杂性,所以除非你真的需要,否则使用平面向量和计算索引会更简单;影像库就是这样做的。
关于第二部分,vitest
s 在每个 push_back 上都被复制。但从 C++11 开始,您可以编写 vvint1.push_back(std::move(vitest1));
(或 vvint1.emplace_back(std::move(vitest1));
)来代替移动。对于向量,这意味着新构建的向量无需复制即可获得vitest1
内容的所有权(因此vitest1
变为空)。这不会改变内存需求,但会减少分配,因为vitest
(在构造时)分配的空间将被重用而不是被释放(在销毁时,在每次迭代结束时)。
【讨论】:
也许是2 * nvvec * sizeof(vector<int>)
? (假设它以nvvec
开头并且有push_back
s)。
糟糕,错过了。谢谢。编辑了答案。以上是关于向量的向量占用的内存的主要内容,如果未能解决你的问题,请参考以下文章