将一种类型的 STL 对象存储到另一种类型的有效方法
Posted
技术标签:
【中文标题】将一种类型的 STL 对象存储到另一种类型的有效方法【英文标题】:Effective way of storing STL object of one type into another type 【发布时间】:2013-03-13 05:17:23 【问题描述】:我有一个 STL 对象,例如
std::vector <long> vec1;
我想将其转换为矢量
std::vector <int> vec2;
使用
std::map<long,int>map;
有没有一种有效的方法来动态删除映射到 vec2 的 vec1 元素以减小 vec1 的大小?这个算法应该消耗最少的内存并且应该很快。是否可以就地执行此操作? std::remove_if 会做好吗?与分块处理相比,性能如何,即 vec1 被分成块;然后将每个块映射并存储在 vec2 中;在此之后从内存中删除块。
vec1(和vec2)也可以是向量(vector of vector)。
【问题讨论】:
为什么不std::map<vector<long>, vector<int>> longToIntMap
我不想在获得 vec2 后将 vec1 存储在内存中
您为什么要完成使用map
的步骤?为什么不简单地循环第一个向量,然后将值推入第二个向量?
除非你想要vector1和vector2?
如果你想“回收”第一个向量使用的内存,那么你可以在复制后简单地clear
它。
【参考方案1】:
有没有一种有效的方法来动态删除映射到 vec2 的 vec1 元素以减小 vec1 的大小?
从vector
的开头删除东西是低效的,因为它会导致剩余的元素向前移动以填充开头的空白空间。而且在向量末尾释放的内存无论如何都不会返回到堆中,因为它都是一个大内存块的一部分,一次全部释放。
这里更适合std::queue
,它默认使用std::deque
数据结构。这包括一系列小内存块。您可以在开头使用pop
释放内存。
#include <queue>
std::queue <long> vec1;
std::queue <int> vec2;
while ( ! vec1.empty() )
vec2.push( value_map[ vec1.front() ] );
vec1.pop();
您也可以直接使用std::deque
对象。然后你会使用push_front
和pop_back
。这是一堂很酷的课;即使对象不在像vector
使用的整体扁平数组中,它也会保持对象“扁平”序列的错觉。
【讨论】:
非常感谢您的建议。因此,即使从向量中弹出元素,它的长度也不会改变(这块内存不会被释放)吗? @SumanVajjala Avector
有一个size()
(包含的有效对象的数量)和一个capacity()
(使用的堆空间量)。 pop_back
、erase
等不影响capacity
。
所以即使 size() = 0,vector 也会保留一些内存(存储大小由 capacity() 给出)?
@SumanVajjala 不,capacity
随着size
的增长呈几何级数增长。 (对于 N 个 push_back
操作,预计 O(log N) 重新分配到更大的 capacity
。)但是当 size
缩小时,capacity
仍处于高水位线。
好的。科尔。再次感谢您的建议/cmets!容量是否保持最高是否重要?转换后 Vec1 将不会在任何地方使用。【参考方案2】:
如果你已经有地图,你可以试试这个 (C++11) 解决方案:
std::vector<long> vec1; // Original vector
std::map<long, int> map; // How to map the `long` value to an `int`
std::vector<int> vec2; // The destination vector
for (const auto l : vec1)
vec2.push_back(map[l]);
如果第一个向量是向量的向量,只需使用嵌套循环:
for (const auto& v : vec1)
for (const auto l : v)
vec2.push_back(map[l]);
【讨论】:
这会在将vec1的元素推入vec2后自动删除它吗? 我不想在处理过程中将vec1的所有元素都存储在内存中。增加内存消耗。有没有一种有效的方法,在向 vec2 添加元素/一些元素后,可以从 vec1 中删除它们(删除和调整大小) @SumanVajjala 查看 WhozCraig 评论中链接到的 SO 问题。 @SumanVajjala 如果您所在的平台内存非常有限,以至于您不能同时在内存中拥有两个向量,那么我建议您应该重新考虑您的算法。除非向量包含数百万个元素,否则即使是 15 年的 PC 也应该能够处理它而不会出现太多问题。 感谢解决方案和 cmets Joachim。虽然这看起来很简单,但如果我有大约 100 万个 long/core 并在这个存储中添加了大约 1000 万个 doubles/core,情况可能会加剧。所以,我一直在寻找能够最大限度地减少内存存储开销的算法!【参考方案3】:您可以在将元素复制到目标向量时从源向量中删除它们。
while (!source.empty())
destination.push_back(map[source.back()]);
source.pop_back();
这需要 O(n log m) 时间和 O(1) 空间,其中 n 是 source.size()
和 m 是map.size()
。
【讨论】:
感谢您的解决方案 :) 我想知道是否有针对此问题的就地黑客或其他东西以上是关于将一种类型的 STL 对象存储到另一种类型的有效方法的主要内容,如果未能解决你的问题,请参考以下文章
将一种类型的 unique_ptr 复制到另一种类型的工作原理
如何将一种泛型类型的结构复制到 TypeScript 中的另一种泛型?