【问题标题】:Can I use always emplace to replace insert for single element insertion?我可以使用 always emplace 替换 insert 以进行单个元素插入吗?
【发布时间】:2014-07-20 02:27:58
【问题描述】:

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

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

注意:有一些问题询问emplaceinsert/push_back 等之间的区别(例如hereherehere)我理解其中的区别,而且看起来对我来说,emplace 在各方面都更好。我只是想确认是否可以弃用insert

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    有一些示例here 可以适应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,除非您明确指定,否则您会收到错误消息。

    【讨论】:

    • 真是个惊喜。谢谢。但是emplace如果不涉及模板应该可以吗?
    • @TingL 你也可以有非模板重载函数。对于这些,手动解析更糟糕(你需要static_cast)。
    【解决方案2】:

    总是?不,当然不是。

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

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

    它是异常安全的。创建一个临时的uptr 以传递给insert,该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>());
    

    它使用标准智能指针并明确创建智能指针。

    【讨论】:

    • @T.C.:如果您决定始终使用 emplace 而不是 insert,您不会注意到这一点。 emplace 会愉快地调用显式构造函数。
    • 对,但第一个示例不是异常安全的——它根本无法编译。
    • 嗯,我认为任何可以从原始指针隐式构造的具有所有权语义的智能指针类型都太危险而无法使用。
    • @T.C.:那么所有可以毫不费力地调用显式构造函数的各种东西,比如emplace,也应该太危险了?是的,explicit 构造函数有助于在其他情况下防止此问题,并且 emplace 很高兴绕过该保护。
    • -1。考虑处理 realloc 失败时引发的异常是浪费时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 2011-03-29
    相关资源
    最近更新 更多