【问题标题】:So what is it that differentiate emplace(c.end(),_1) from emplace_back(_1)?那么 emplace(c.end(),_1) 和 emplace_back(_1) 的区别是什么?
【发布时间】:2013-02-17 10:34:34
【问题描述】:

我认为使用 emplace(c.end(),_1) 与 emplace_back(_1) 相同 但我不明白为什么语言设计者给出了两个功能而不是一个。 我假设我遗漏了一些信息。

那么 emplace(c.end(),_1) 和 emplace_back(_1) 的区别是什么?

【问题讨论】:

    标签: c++ c++11 std


    【解决方案1】:

    emplace相比,vector::emplace_backdeque::emplace_back对容器value_type的要求降低了。

    仅代表vectordeque

    除了EmplaceConstructible来自args

    emplace 需要 MoveInsertableMoveAssignable,而

    emplace_back 只需要MoveInsertable

    对于大多数分配器,包括std::allocatorMoveInsertableMoveConstructible 相同。

    因此,如果您有一个类型要放入vectordeque,它是MoveConstructible,但不是MoveAssignableemplace_back 是您的朋友。它也可能稍微更快,并且代码大小稍微更小,但这是一个实现质量问题(标准不保证)。并且差异可能比您注意到的要小(除非仔细测量)。

    例如,给定:

    #include <vector>
    
    struct A
    {
        A() = default;
        A(A&&) = default;
        A& operator=(A&&) = delete;
    };
    

    这样编译:

    int main()
    {
        std::vector<A> v;
        v.emplace_back();
    }
    

    但这不是:

    int main()
    {
        std::vector<A> v;
        v.emplace(v.end()); //  error A is not MoveAssignable
    }
    

    但是如果我改变了:

        A& operator=(A&&) = delete;
    

    到:

        A& operator=(A&&) = default;
    

    那么这两个例子都会编译(并且运行良好)。

    【讨论】:

    【解决方案2】:

    根据数据结构,有可能使emplace_backemplace(c.end(), _1) 更快。例如,使用std::vectoremplace_back 不必检查哪些(如果有)元素需要移动,使emplace_back 稍微快一些。

    【讨论】:

      【解决方案3】:

      是的,在这种情况下它们是等价的。

      emplace 更通用,因为它不仅仅在最后起作用; emplace_back 很方便,因为你不必写c.end()

      实现也可能有好处 - 请记住 emplace知道您提供给它的迭代器是 end 迭代器。

      就是这样。

      【讨论】:

      • 不遵循this best practice 的有趣案例。 insert()push_back() 我猜也是一样。
      • 血腥标准。容器操作要求是这样定义的,以至于我找不到简明正式地证明这种等价性的方法。噗。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2021-10-13
      • 2013-02-25
      • 2020-06-17
      • 1970-01-01
      • 2014-12-14
      相关资源
      最近更新 更多