为什么这个std :: vector :: emplace_back会失败?

时间:2018-02-18 09:01:24

标签: c++ constructor stdvector

我遇到了编译错误:

  

尝试引用已删除的功能

#include <iostream>
#include <vector>

template <typename T>
struct Container
{
    Container() = default;
    Container(const Container& other) = delete;
    Container(T* ptr) : ptr(ptr) {}
    T* ptr;
    ~Container() { delete ptr; }

};

struct Foo { Foo(int a, int b) {} };

int main()
{
    std::vector<Container<Foo>> myvector;
    myvector.push_back(new Foo(1, 2)); // I understand why this doesn't work.
    myvector.emplace_back((new Foo(1, 2))); // I don't understand why this fails

}

我理解为什么当我执行std::vector::push_back()时它试图引用已删除的构造函数,因为这会复制并需要调用复制构造函数,我删除了。

但是std::vector::emplace_back()应该采用它所拥有的类型的构造函数参数。当我向后移动时,我给它一个指向Foo的指针,这应该转发给Container::Container(T* ptr)构造函数。

我错过了什么?

1 个答案:

答案 0 :(得分:19)

声明用户定义的复制构造函数不会定义隐式移动构造函数; T必须要有复制构造函数移动构造函数push_backemplace_back*对象为std::vector<T>

docs,查看T上的要求,以实例化std::vector<T>。 (这里没有限制,请继续阅读).. 强调我的

  

对元素施加的要求取决于对容器执行的实际操作 。通常,要求元素类型满足Erasable 的要求,但许多成员函数强加了更严格的要求 。如果分配器满足分配器完整性要求,则可以使用不完整的元素类型实例化此容器(但不是其成员)。

来自std::vector<...>::push_back

  

类型要求

     
      
  • T必须符合 CopyInsertable 的要求才能使用overload(1)。
  •   
  • T必须符合 MoveInsertable 的要求才能使用overload(2)。
  •   

来自std::vector<...>::emplace_back

  

类型要求

     
      
  • T(容器的元素类型)必须满足 MoveInsertable EmplaceConstructible 的要求。
  •   

对于此处emplace_back,您的代码将符合 EmplaceConstructible 标准,但是,由于可能会发生重新分配,您必须同样满足 MoveInsertable