我可以使用总是置地来代替单个元素插入的插入吗?

Can I use always emplace to replace insert for single element insertion?

本文关键字:插入 元素 单个 可以使 我可以      更新时间:2023-10-16

我想知道在将单个元素插入 STL 容器(如 set、unordered_set(时,是否可以始终使用 emplace 来替换insert

从签名来看,emplace更简单,不涉及重载。停止使用insert并一直使用emplace有什么问题吗?

注意:有 SO 问题询问 emplaceinsert/push_back 等之间的区别(例如这里、这里和这里(我理解其中的区别,在我看来,emplace各方面都更好。我只是想确认是否可以弃用insert.

这里有一些例子可以适应emplaceinsert,显示行为何时可能不同。

这些例子可能看起来有点人为,所以我会举一个希望看起来不那么像

人心的例子:
#include <set>
template <typename T>
T id(T x) { return x; }
int main() {
    std::set<int(*)(int)> s;
    s.insert(id);       // OK
    s.emplace(id);      // error
    s.emplace(id<int>); // OK
}

insert可以推断出id的模板参数,因为它知道自己想要什么类型。对于emplace,除非您明确指定,否则会出现错误。

总是? 不,当然不是。

考虑以下示例,该示例使用std::vector为简单起见(假设uptr是一个智能指针,通常与std::unique_ptr类似(:

std::vector<uptr<T>> vec;
vec.insert(vec.begin(), new T());

它是异常安全的。 一个临时uptr被创建传递给insert,它被移动到向量中。 如果矢量的重新分配失败,则分配的T由智能指针拥有,该指针会正确删除它。

比较:

std::vector<std::uptr<T>> vec;
vec.emplace(vec.begin(), new T());

不允许emplace创建临时对象。 uptr将在矢量中就地创建一次。 如果重新分配失败,则没有就地创建的位置,并且不会初始化任何智能指针。 T将被泄露。

当然,最好的选择是:

std::vector<std::unique_ptr<T>> vec;
vec.insert(vec.begin(), make_unique<T>());

它使用标准智能指针并使智能指针创建显式。