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

Why does this std::vector::emplace_back fail?

提问人:Zebrafish 提问时间:2/18/2018 最后编辑:WhiZTiMZebrafish 更新时间:2/19/2018 访问量:2596

问:

我遇到了一个编译器错误,上面写着:

尝试引用已删除的函数

#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()FooContainer::Container(T* ptr)

我错过了什么?

C++ 构造函数 StdVector

评论

1赞 WhiZTiM 2/18/2018
定义复制构造函数不会定义隐式移动构造函数;您需要将对象复制构造函数或移动到向量中emplace*
0赞 Zebrafish 2/18/2018
@WhiZTiM 哦,emplace_back提出论点?我以为它直接使用placement new或类似的东西调用构造函数,直接构造它。
8赞 user2357112 2/18/2018
它不会,但它可能会触发调整大小,并且必须能够移动或复制元素。
3赞 user7860670 2/18/2018
@Zebrafish 它可以调用现有矢量项的移动构造函数。
0赞 Zebrafish 2/18/2018
@VTT哦,我明白了,这是以防万一它必须重新分配向量......

答:

19赞 WhiZTiM 2/18/2018 #1

声明用户定义的复制构造函数不会定义隐式移动构造函数; 必须将复制构造函数或将构造函数移动到 或将对象移动到 .Tpush_backemplace_back*std::vector<T>

文档中,请参阅实例化 .(这里没有限制,请继续阅读)..强调我的Tstd::vector<T>

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

std::vector<...>::p ush_back

型号要求

  • T必须满足 CopyInsertable 的要求才能使用重载 (1)。
  • T必须满足 MoveInsertable 的要求才能使用重载 (2)。

std::vector<...>::emplace_back

型号要求

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

在这里,您的代码将满足 EmplaceConstructible 条件,但是,由于可能会发生实现,因此您同样必须满足 MoveInsertableemplace_back