std :: vector emplace_back()用于非复制可构造对象

Mir*_*pas 12 c++ vector c++11

考虑en.cppreference.com关于的引用std::vector::emplace_back

"将一个新元素追加到容器的末尾.该元素就地构造,即不执行复制或移动操作.使用提供给函数的完全相同的参数调用元素的构造函数."

以下样本:

#include <vector>
struct A
{
    A(int){}
    A(A const&) = delete;
};

int main()
{
    std::vector<A> vec;
    vec.emplace_back(1);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在线vec.emplace_back(1);Visual Studio 2013/GCC报告:

错误C2280:'A :: A(const A&)':尝试引用已删除的函数

错误:使用已删除的函数'A :: A(const A&)'

错误是否正确?你能解释一下为什么吗?

Rei*_*ica 12

C++ 11 23.2.1表101说明:

表达: a.emplace_back(args)

返回类型: void

操作语义:追加T构造类型的对象std::forward<Args>(args)....要求: TEmplaceConstructibleXargs.因为vector,T也应该MoveInsertable进入X.

A没有满足MoveInsertable要求,因为您没有移动构造函数,并且只有一个已删除的复制构造函数.使用其他容器std::vector,它可以工作.


Ste*_*sop 7

与增加向量大小的其他函数一样,emplace_back有条件地重新分配向量(如果当前容量不够大).如果它这样做,那么它需要将旧数组中的现有元素转换为新数组.

您的类没有移动构造函数(某些类具有编译器生成的移动,但不是因为您删除了复制构造函数).因此重新分配代码需要能够复制类型,而不能.

当然,对于这个调用,没有要复制的旧元素,但是该emplace_back函数无法实例化.