为什么只有非常量映射提供类似于关联数组的直接元素检索?

Why do only non-constant maps provide associative array-like direct element retrieval?

本文关键字:数组 元素 检索 关联 类似于 非常 常量 映射 为什么      更新时间:2023-10-16

我正在阅读:

标准c++库:教程和参考(Nicolai M. Jossuttis)

当我要以任何重要的方式使用一些STL机制时,这是我的首选书籍。无论如何,我很快重读了std::map和相关算法的章节,我注意到一个我以前没有想过的句子:

非常量映射为直接访问元素提供了下标操作符。但是,下标操作符的下标不是元素. ...的整型位置等。

为什么只有非常数映射可以像关联数组那样使用?在这种情况下,提供只读语义似乎相当简单。我想,如果你试图检索一个键不存在的元素(因为你不能添加一个新的键/值到映射,如果它是常量),可能会出现异常。

我想了解背后的原因,如果有人能透露一些光:)谢谢!

为什么只能在关联数组中使用非常量映射的方式吗?

因为这些操作符返回与特定键相关联的对象的引用。如果容器还没有包含这样的对象,operator[]将插入默认对象。现在,如果容器是常量,则不能向其中插入任何对象,也不能返回对不存在的对象的引用,这就是为什么这些操作符仅对非常量容器可用。

当然,在这种情况下抛出异常是可能的,但当给定键的对象不存在时,这并不是处理一般情况的最佳方法。基本上,异常是非常昂贵的,并且是用于特殊情况的,而上面的异常不是,所以不值得使用。

更好的方法是返回一个迭代器,但用户必须检查它是否为"end",这将使用例类似于调用find (),因此无用。也可以为纯常量容器返回迭代器或指针,但这会稍微破坏语义并使人困惑。

在c++ 11中,您可以使用at()来获得"获取映射值,否则抛出异常"的行为。重载operator[]做两种不同的事情(即要么插入新的对或抛出)取决于是否映射是常数将太混乱和容易出错。

[]操作符修改映射,如果键不存在。

如果键不存在,则映射用该键创建一个新条目,并为关联值创建一个默认值,并返回其引用。要做到这一点,operator[]必须是非const函数,这意味着它不能操作std::mapconst实例。

[] -操作符改变容器:如果密钥不存在,它将被创建:

return m[1];      // **creates** m[1] if it doesn't exist
return *m.find(1) // UB if m[1] doesn't exist (dereferencing m.end())

此外,[]总是返回一个非常量引用,因此您可以说m[1] = 2;。另一方面,find()返回一个constness为map本身的迭代器:

map_t m;
*m.find(1) = 2;    // Only OK if m[1] exists
// *const_cast<map_t const &>(m).find(1) = 2;  // error