27

根据 cppreference.com,std::map::operator[]对于不存在的值进行零初始化。

但是,同一个站点没有提到零初始化std::unordered_map::operator[],除了它确实有一个依赖于此的示例。

当然这只是一个参考站点,不是标准。那么,下面的代码可以吗?

#include <unordered_map>
int main() {
    std::unordered_map<int, int> map;
    return map[42];     // is this guaranteed to return 0?
}
4

2 回答 2

23

在您链接的网站上,它说:

当使用默认分配器时,这会导致键是从键复制构造的,并且映射的值是值初始化的。

所以int值初始化的

值初始化的效果是:

[...]

4) 否则,对象被零初始化

这就是为什么结果是0

于 2019-12-05T09:51:29.727 回答
16

根据我们谈论的重载,std::unordered_map::operator[]相当于[unord.map.elem]

T& operator[](const key_type& k)
{
    return try_­emplace(k).first->second;
}

(采用右值引用的重载只是移动ktry_emplace并且在其他方​​面是相同的)

k如果map 中的key 下存在元素,则try_emplace返回该元素的迭代器和false. 否则,try_emplace在 key 下插入一个新元素k,并返回一个迭代器和true [unord.map.modifiers]

template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);

对我们来说有趣的是还没有元素的情况[unord.map.modifiers]/6

否则插入一个由value_­type构造的类型的对象piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...)

(采用右值引用的重载只是移动kforward_­as_­tuple并且再次相同)

由于value_typepair<const Key, T> [unord.map.overview]/2,这告诉我们新的地图元素将被构造为:

pair<const Key, T>(piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...));

由于args来自 时为空operator[],这归结为我们的新值被构造为pairfrom 无参数[pairs.pair]/14的成员,这是使用类型值的直接初始化[class.base.init]/7作为初始化器,归结为值初始化[dcl.init]/17.4。an 的值初始化为零初始化[dcl.init]/8。an 的零初始化自然会将其初始化为 0 [dcl.init]/6T()intintint

所以是的,你的代码保证返回 0…

于 2019-12-05T10:10:30.053 回答