是否可以有一个非常量键类型的无序映射

Is it possible to have an unordered_map with non-const key type?

本文关键字:类型 无序 映射 常量 有一个 非常 是否      更新时间:2023-10-16

本质上,我想要一个容器,其中一个元素可以被多个键访问。这可以通过定义一些多键类作为映射的键类型来实现,但由于这样的解决方案不允许修改已经插入的元素的键,因此我无法为现有条目创建新的别名。

我理解使用std::map时,为了排序的目的,密钥需要是常量,但为什么std::unordered_map要存在这种限制?

如果需要的话,我想我可以使用指针映射,但有更好、更优雅的解决方案吗?

编辑:谢谢你澄清安德烈,谢。尼科尔,关于我应该使用什么容器,有什么建议吗?

std::unordered_map不允许修改键的原因与其他关联容器不允许修改它的原因大致相同:它会扰乱数据结构的内部组织。

unordered_map中,密钥用于获得一个散列,该散列告诉容器将元素放置在哪个桶中(当然还有从哪个桶中检索元素)。如果你修改了密钥,你就修改了散列,这意味着你的元素应该被移到另一个bucket中。基本上,这就像把它取下来再插入。

另一方面,关联容器的整体思想是,任何元素都由一个固定的值表示,因此它在容器中的位置可以作为该值的函数快速计算。如果允许使用多个键,您会使用哪一个键来快速确定元素的存储位置或将要存储的位置?

您想要的可能是一个特设数据结构,其复杂性保证不同于标准库。

然而,就我个人而言,您似乎只是在寻找引用语义,因为您打算共享一个对象的多个视图。这自然会让我使用(智能)指针,尤其是当我听到这个世界的"别名"时。我建议你选择一张以shared_ptrs为值的地图。

在关联容器(例如mapunordered_map)中,key的值决定元素在数据结构中的位置。在非多重关联容器中,关键帧也是唯一的。

如果允许修改key,那么这将危及前面提到的设计不变量。

  • map中,元素在二进制搜索树中的位置

  • unordered_map中,将元素链接到散列桶

如果我理解OP的需求,那么它可以通过在容器的insert()上编写一个包装器来实现,比如下面的C++伪代码:

Iterator insert_wrapper( Container & cont, Element const & elem ) {
    if elem in cont {
       cont.erase( elem );
    }
    return cont.insert( elem );
}

你会发现引用映射比指针映射更有品味吗?

int value = 6;
std::unordered_map<int, int&> m;
for(int i=0; i<5; ++i)
    m.emplace(i, value);
value = 4;
for(auto const& i: m)
    std::cout<<i.second<<' ';

当然,您必须将实际值存储在其他地方,如示例所示。