插入 std::map 时强制初始化为 0

Force initialization to 0 when inserting into a std::map

我有一个 std::map<std::string,std::size_t> 键映射计数器。当我增加一个计数器时,我不知道它是否已经存在。如果是,则增加。如果不是,则设置为1。这很容易做到:

std::map<std::string,std::size_t> counters;
//...
auto c_it = counters.find(key);
if(c_it == counters.end())
  counters.insert(key,1);
else
  (*c_it)++;

这是一个简单的事情的大量代码......我想这样做:

counters[key]++;

但这会产生未定义的行为,因为当映射中不存在计数器时会调用 std::size_t(),并且无法保证 std::size_t() 初始化为 0。

我看到两个可能的解决方案:

  1. 查找/创建类似于 std::size_t 的类型,在使用默认构造函数创建时强制初始化为 0。 stdboost 中有这样的类型吗?
  2. 查找/创建一个专用分配器来替换作为 std::map 的第 4 个模板参数给出的默认 std::allocator<std::pair<const Key,T>>。但是我不知道该怎么做。

注意:我只使用C++11(我不想要C++>=14的解决方案)

++counters[key]; 完全有效。 std::map::operator[] 如果映射中不存在该键,则插入一个值初始化的元素。这是执行您所解释内容的惯用方式。

But this generates undefined behavior because std::size_t() is called when the counter doesn't exist in the map, and there is no guarantee that std::size_t() initializes to 0.

这个假设是不正确的。引自 cppreference:

If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise) and a reference to it is returned.

引用是针对 C++11 之前的版本,但更容易理解元组魔法和可观察到的效果是相同的。

该值将被零初始化,您可以毫无问题地使用counters[key]++;