【问题标题】:Does std::unordered_map operator[] do zero-initialization for non-exisiting key?std::unordered_map operator[] 是否对不存在的键进行零初始化?
【发布时间】:2020-03-30 05:06:51
【问题描述】:

根据 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?
}

【问题讨论】:

  • @Ælex 您无法可靠地测试某些内容是否已初始化
  • @Ælex 我不太明白,你怎么会有一个未初始化的std::optional
  • @Ælex 无法测试对象是否已初始化,因为除了初始化之外对未初始化对象的任何操作都会导致未定义行为。不包含任何值的 std::optional 对象仍然是已初始化的对象。
  • 值对象是值初始化的,而不是零初始化的。对于标量类型,它们是相同的,但对于类类型,它们是不同的。
  • @bolov 我昨天尝试使用 gnu 17 和 std 17 对其进行测试,但奇怪的是我得到的只是零初始化。我以为 std::optional has_value 会测试它,但它失败了,所以我猜你是对的。

标签: c++ unordered-map zero-initialization


【解决方案1】:

根据我们所说的重载,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 将返回该元素的迭代器和 false。否则,try_emplace 在键 k 下插入一个新元素,并返回一个迭代器和 true [unord.map.modifiers]

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

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

否则插入使用piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward&lt;Args&gt;(args)...)构造的value_­type类型的对象

(采用右值引用的重载只是将k 移动到forward_­as_­tuple 中,并且在其他方​​面是相同的)

由于value_typepair&lt;const Key, T&gt; [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 这是直接初始化[class.base.init]/7 的值键入T 使用() 作为初始化程序,归结为值初始化[dcl.init]/17.4int 的值初始化为零初始化 [dcl.init]/8int 的零初始化自然会将 int 初始化为 0 [dcl.init]/6

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

【讨论】:

    【解决方案2】:

    在您链接的网站上显示:

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

    所以intvalue-initialized

    值初始化的效果是:

    [...]

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

    这就是为什么结果是0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 2016-10-07
      • 2020-10-20
      • 2013-01-19
      • 2021-09-11
      相关资源
      最近更新 更多