C++中map[]和map.at的区别?

问题描述 投票:0回答:3

C++中通过

aMap[key]
aMap.at(key)
获取值有什么区别?

c++ c++11 stl
3个回答
46
投票

如果您使用索引运算符

[]
访问当前不属于地图一部分的键,那么它会自动为您添加一个键。这是一个巨大的警告,请考虑到这一点。因此,我更喜欢使用索引运算符
[]
进行设置,使用
.find()
/
.at()
进行查找。

使用

.at()
相对于
[]
的另一个优点是它可以在
const std::map
上运行,而
[]
则不能。


26
投票

在 C++11 中

map::at
存在(谁知道?)。

如果键不存在,它会抛出异常;如果元素不存在,

find
返回
aMap.end()
;如果相应键不存在值,
operator[]
值初始化会为相应键返回一个新值。


0
投票

我喜欢这里的答案,但我认为了解为什么 [] 不能在

const
std::map
实例上使用很重要。如果我们看一下这些方法的标准声明:

mapped_type& at(const key_type& k);
const mapped_type& at(const key_type& k) const;
mapped_type& operator[](const key_type& k);
mapped_type& operator[](key_type&& k);

正如我们所见,所有

operator[]
都不是
const
,因此返回的
mapped_type
是可以修改的。另一方面,存在一个
const& at() const
版本,它不允许修改mapped_type,也不允许修改类本身。

现在让我们看看为什么在

operator[]
的实现中会出现这样的情况:

template <class _Key, class _Tp, class _Compare, class _Allocator>
_Tp&
map<_Key, _Tp, _Compare, _Allocator>::operator[](const key_type& __k)
{
    return __tree_.__emplace_unique_key_args(__k,
        _VSTD::piecewise_construct,
        _VSTD::forward_as_tuple(__k),
        _VSTD::forward_as_tuple()).first->__get_value().second;
}

在这里我们可以看到,该方法尝试将密钥作为新的唯一密钥对直接放入二叉树中,然后 emplace 方法返回对

std::pair
的引用(无论它是否已经存在)。这棵树是
std::map
的成员,因此返回对其数据的引用可能会修改数据,并且与树本身一起修改数据,从而修改
std::map
类,这就是为什么不可能在
const 上调用此方法
std::map
的实例。

现在我们来看看

at() const
的实现:

template <class _Key, class _Tp, class _Compare, class _Allocator>
const _Tp&
map<_Key, _Tp, _Compare, _Allocator>::at(const key_type& __k) const
{
    __parent_pointer __parent;
    __node_base_pointer __child = __tree_.__find_equal(__parent, __k);
    if (__child == nullptr)
        __throw_out_of_range("map::at:  key not found");
    return static_cast<__node_pointer>(__child)->__value_.__get_value().second;
}

此方法以完全不同的方式访问树。因为它只搜索已经存在于树中的相等项。并使用指向找到的节点的常量指针进行操作。

const
方法的非
at()
版本的操作非常相似,但它请求
__node_base_pointer
作为参考,从而可以修改它,但仍然消除了用
at()放置新节点的可能性
方法。

© www.soinside.com 2019 - 2024. All rights reserved.