插入 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。
我看到两个可能的解决方案:
- 查找/创建类似于
std::size_t
的类型,在使用默认构造函数创建时强制初始化为 0。 std
或 boost
中有这样的类型吗?
- 查找/创建一个专用分配器来替换作为
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]++;
。
我有一个 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。
我看到两个可能的解决方案:
- 查找/创建类似于
std::size_t
的类型,在使用默认构造函数创建时强制初始化为 0。std
或boost
中有这样的类型吗? - 查找/创建一个专用分配器来替换作为
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 thatstd::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]++;
。