std::map::emplace
创建对象(即调用构造函数)的点是以标准方式指定的吗?如果是,是否会在检查之前是否存在此类密钥?
在以下情况下,这很重要:
struct X {};
std::map<int, std::unique_ptr<X> > map;
void f(int x) {
map.emplace(x, new X);
}
如果首先创建对象,那么一切都很酷(构造unique_ptr并拥有资源),但如果在检查后构造它,则在重复键的情况下会发生内存泄漏。
我能在标准中找到所有
插入一个用_构造的value_type对象
std::forward<Args>(args)...
当且仅当时没有元素 密钥等效于t的密钥的容器。
没有解决我的问题。
答案 0 :(得分:12)
这确实是未明确的,这部分是为什么C ++ 17添加try_emplace
来确定语义。 N3873是try_emplace
提案的早期版本,对现有措辞进行了很好的讨论。
在一般情况下,它必须是“之前”,因为“之后”是不可实现的,如果它强加了这样的要求,标准就会有缺陷。考虑emplace(piecewise_construct, forward_as_tuple(foo, bar), forward_as_tuple(meow, purr))
。因为键和值不需要是可移动的,所以你几乎必须首先构造对象并检查键的存在,因为你不能在没有键的情况下检查键的存在。
然而,实现可能需要特殊情况emplace(key_type, something)
并不是不可想象的;当密钥存在时,避免支付所需的分配+构造+销毁+解除分配通常是一件好事。