std::unordered_map operator[] 是否对不存在的密钥进行零初始化?
Does std::unordered_map operator[] do zero-initialization for non-exisiting key?
根据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?
}
在您链接的网站上写着:
When the default allocator is used, this results in the key being copy
constructed from key and the mapped value being value-initialized.
所以 int
是 value-initialized:
The effects of value initialization are:
[...]
4) otherwise, the object is zero-initialized
这就是为什么结果是 0
。
根据我们谈论的重载,std::unordered_map::operator[]
等价于 [unord.map.elem]
T& operator[](const key_type& k)
{
return try_emplace(k).first->second;
}
(采用右值引用的重载只是将 k
移动到 try_emplace
中,否则是相同的)
如果映射中的键 k
下存在一个元素,则 try_emplace
return 是该元素的迭代器和 false
。否则,try_emplace
将在键 k
下插入一个新元素,并且 return 是该元素的迭代器,并且 true
[unord.map.modifiers]:
template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
我们感兴趣的是还没有元素的情况[unord.map.modifiers]/6:
Otherwise inserts an object of type value_type
constructed with piecewise_construct, forward_as_tuple(k), forward_as_tuple(std::forward<Args>(args)...)
(采用右值引用的重载只是将 k
移动到 forward_as_tuple
中,并且在其他方面也是相同的)
因为 value_type
是 pair<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[]
时为空,这归结为我们的新值被构造为 pair
的成员,没有参数 [pairs.pair]/14 which is direct initialization [class.base.init]/7 of a value of type T
using ()
as initializer which boils down to value initialization [dcl.init]/17.4. Value initialization of an int
is zero initialization [dcl.init]/8. And zero initialization of an int
naturally initializes that int
to 0 [dcl.init]/6。
所以是的,你的代码保证 return 0…
根据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?
}
在您链接的网站上写着:
When the default allocator is used, this results in the key being copy constructed from key and the mapped value being value-initialized.
所以 int
是 value-initialized:
The effects of value initialization are:
[...]
4) otherwise, the object is zero-initialized
这就是为什么结果是 0
。
根据我们谈论的重载,std::unordered_map::operator[]
等价于 [unord.map.elem]
T& operator[](const key_type& k)
{
return try_emplace(k).first->second;
}
(采用右值引用的重载只是将 k
移动到 try_emplace
中,否则是相同的)
如果映射中的键 k
下存在一个元素,则 try_emplace
return 是该元素的迭代器和 false
。否则,try_emplace
将在键 k
下插入一个新元素,并且 return 是该元素的迭代器,并且 true
[unord.map.modifiers]:
template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
我们感兴趣的是还没有元素的情况[unord.map.modifiers]/6:
Otherwise inserts an object of type
value_type
constructed withpiecewise_construct, forward_as_tuple(k), forward_as_tuple(std::forward<Args>(args)...)
(采用右值引用的重载只是将 k
移动到 forward_as_tuple
中,并且在其他方面也是相同的)
因为 value_type
是 pair<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[]
时为空,这归结为我们的新值被构造为 pair
的成员,没有参数 [pairs.pair]/14 which is direct initialization [class.base.init]/7 of a value of type T
using ()
as initializer which boils down to value initialization [dcl.init]/17.4. Value initialization of an int
is zero initialization [dcl.init]/8. And zero initialization of an int
naturally initializes that int
to 0 [dcl.init]/6。
所以是的,你的代码保证 return 0…