std::unordered_map<int32_t, int32_t> 在堆上声明

Posted

技术标签:

【中文标题】std::unordered_map<int32_t, int32_t> 在堆上声明【英文标题】:std::unordered_map<int32_t, int32_t> declared on heap 【发布时间】:2016-11-29 06:49:49 【问题描述】:

在堆上声明一个std::unordered_map,对其执行一些操作,然后释放它的语法是什么?我在做:

std::unordered_map<int32_t, int32_t> *map_temp_last_close = new std::unordered_map<int32_t, int32_t>;
*(map_temp_last_close[val]) = *(int32_t*)(read_buffer + 30); //this happens multiple times in a loop
int32_t some_val = val * (*(map_temp_last_close[val]))
map_temp_last_close->clear();
delete(map_temp_last_close);

编辑: 为什么我需要把它放在堆上?我有一个始终运行的函数,它不断地从网络接收数据,在某些情况下,将数据存储在地图中以进行处理。一旦地图的使用结束,我知道我不会在我的协议中再次收到该消息,因此不需要地图,但地图并没有超出范围,因为函数处于无限循环中(阻塞时网络阅读)。所以我想通过调用freedelete 或其他方式来释放内存。

【问题讨论】:

为什么需要在堆中这样做?为什么不在堆栈中? @SergeRoussak 查看编辑。 @user2635088:本地堆栈变量(正式地,具有自动存储持续时间的本地变量)在封闭范围的末尾被销毁,它可以小于函数。使用 在函数内创建范围。或者,就像您已经在做的那样,在map 上调用clear(),这将恢复重要的资源(sizeof (unordered_map) 可以忽略不计,相关的堆数据可能大到足以引起关注,并且clear() 应该注意这一点)。 你是说,你是从另一个线程中删除地图吗?如果是这样,您应该非常小心 - 确保您在两个线程之间使用了同步原语。 @BenVoigt 明白了。我认为clear 应该这样做。谢谢 【参考方案1】:

您的错误是大括号的定位。您必须首先取消引用,然后索引到数据结构中。

我也不会把它放在堆上,因为std::unordered_map已经在内部将它的数据存储在堆上,但是如果你真的需要,我能想到的最简单和最安全的方法是:

auto map_temp_last_close = std::make_unique<std::unordered_map<int32_t, int32_t>>() 
(*map_temp_last_close)[val] = *(int32_t*)(read_buffer + 30); 
int32_t some_val = val * (*map_temp_last_close)[val];

//map object will get destroyed automatically when map_temp_last_close goes out of scope, but if you want to delete it earlier, you can use:
map_temp_last_close.reset();

这会在堆上创建一个std::unordered_map 和一个管理它的本地unique_ptr 变量:每当map_temp_last_close 超出范围(无论是通过返回、异常还是仅仅因为当前范围结束),它都会自动删除地图。此外,没有理由在销毁之前调用clear,因为地图会自动执行此操作。

注意: 很可能(取决于 read_buffer 的类型)这个表达式:*(int32_t*)(read_buffer + 30) 是未定义的行为。

【讨论】:

谢谢。所以read_buffer 是我在调用recv 时从网络接收字节时填充的字符数组。如果网络协议规定在那个位置会有一个 int32_t,这仍然是未定义的行为吗?我知道如果我读取的int32_t 值超出了一定范围,那么协议中有错误,我可以相应地处理该行为 @user2635088: 是的,它在两个方面是未定义的行为,首先是违反严格别名,其次是违反对齐(@9​​87654332@ 不是sizeof (int32_t) 的倍数)。请改用memcpy(&amp;some_val, read_buffer+30, 4) 来获取值。如果您有一个允许错位的平台,编译器将生成一个 32 位移动,每一位都与原始移动一样有效,但行为在形式上是明确定义的。在对齐很重要的平台上,您将获得工作代码。 @BenVoigt 我可以使用memcpy 复制到 (*map_temp_last_close)[val] 吗?会是memcpy(&amp;((*map_temp_last_close)[val]), read_buffer+30, 4);吗? @user2635088:是的,你可以,对于std::unordered_mapoperator[] 返回T&amp; 的任何其他集合。只是不要尝试使用std::vector&lt;bool&gt;

以上是关于std::unordered_map<int32_t, int32_t> 在堆上声明的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能增加 std::unordered_map 迭代器?

Javascript中C++ std::unordered_map<char, int> 的等价物是啥?

std::unordered_map::clear() 做啥?

C++ std::unordered_map 中使用的默认哈希函数是啥?

如何同时填充 std::unordered_map ?

无法创建元组的 unordered_map<int, int, int>