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

时间:2014-04-10 13:02:44

标签: c++ c++11 vector

考虑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;
}

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

  

错误C2280:&#39; A :: A(const A&amp;)&#39; :尝试引用已删除的函数

     

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

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

2 个答案:

答案 0 :(得分:12)

C ++ 11 23.2.1表101说明:

  

表达式:a.emplace_back(args)

     

返回类型:void

     

操作语义:追加由T构造的std::forward<Args>(args)...类型的对象。 要求: TEmplaceConstructible X args vector。对于TMoveInsertable也应为X A

您的MoveInsertable不符合std::vector要求,因为您没有移动构造函数,并且只有一个已删除的复制构造函数。使用{{1}}以外的容器,it works

答案 1 :(得分:7)

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

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

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