在 MSVC 2017 中使用 std::unordered_map<std::string_view, std::string_view> 时,我遇到了一个相对奇怪的段错误,为 C++17 进行编译,并进行了简单的调试构建。
这里的 TLDR 是,在字符串视图“查看”的 char 数组发生更改或超出范围后,在我的地图上调用 .clear() 会导致段错误。
在研究了无序映射的内部结构之后,在我看来,调用 .clear() 假设可以正确计算映射中每个键的哈希值。我想这只是满足标准规定的 O(container_size) 时间复杂度的一种方法。
现在,在我的字符串视图的无序映射的情况下,我相信字符串视图的哈希是基于它所查看的 char 数组的哈希,因此如果 char 数组超出范围,或者以任何方式修改,我的散列将完全关闭,导致段错误。
然而,这似乎是一种非常奇怪的实现无序映射容器的 .clear() 函数的方法。为什么 .clear() 不依赖某种内部状态来决定在调用 Clear 时从哪里开始擦除?这样,当调用 .clear() 时,它就不必依赖可正确计算的密钥哈希。
这是否意味着无法在存储不拥有底层内存且其散列基于底层内存的键的 unordered_map 上安全地调用 .clear() ?
谁能解释一下吗?
谢谢!
我希望对 .clear() 的调用永远不会导致 UB,无论我在地图中使用什么键。我希望对 .clear() 的调用完全独立于键本身的散列。
该标准对任何“无序”容器中的键的行为提出了一些期望:
对于同一容器中的任意两个键,调用
k1应始终返回相同的值。对于容器中的任何键,调用应始终返回相同的值。k2pred(k1, k2)khash(k)
这些是您的关键对象必须遵守的规则。始终:只要容器存在,这些就必须成立。如果它们不成立,您就会得到未定义的行为。
这些语句不提供异常clear,甚至不提供析构函数。因此,任何实现都可以假设容器在任何函数调用期间仍然可以工作clear,包括析构函数。
clear如果您违反了规则,是否可以以一种仍然有效的方式来实现该类型?或许。但他们不必这样做,因为您的代码才是最终出现错误的代码。
| 归档时间: |
|
| 查看次数: |
128 次 |
| 最近记录: |