将一种类型的 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&lt;vector&lt;long&gt;, vector&lt;int&gt;&gt; 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_frontpop_back。这是一堂很酷的课;即使对象不在像vector 使用的整体扁平数组中,它也会保持对象“扁平”序列的错觉。

【讨论】:

非常感谢您的建议。因此,即使从向量中弹出元素,它的长度也不会改变(这块内存不会被释放)吗? @SumanVajjala A vector 有一个size()(包含的有效对象的数量)和一个capacity()(使用的堆空间量)。 pop_backerase等不影响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) 空间,其中 nsource.size() mmap.size()

【讨论】:

感谢您的解决方案 :) 我想知道是否有针对此问题的就地黑客或其他东西

以上是关于将一种类型的 STL 对象存储到另一种类型的有效方法的主要内容,如果未能解决你的问题,请参考以下文章

将一种类型的 unique_ptr 复制到另一种类型的工作原理

向量从一种类型到另一种c ++的隐式转换

如何将一种泛型类型的结构复制到 TypeScript 中的另一种泛型?

如何使用算法将一种类型的列表映射到现代 C++ 中的另一种类型的列表

将一种结构复制到另一种结构

stl中顺序性容器,关联容器两者粗略解释