std::vector emplace_back() 表示非复制可构造对象

std::vector emplace_back() for non copy constructible objects

本文关键字:复制 对象 表示 emplace vector back std      更新时间:2023-10-16

考虑 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:"A::A(常量 A &(":尝试引用已删除的函数

错误:使用已删除的函数"A::A(const A&(">

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

C++11 23.2.1 表 101 指出:

表达式:a.emplace_back(args)

返回类型:void

操作语义:追加使用 std::forward<Args>(args)... 构造的 T 类型的对象。需要: T应从args EmplaceConstructible X。对于vectorT也应MoveInsertable X

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

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

您的类没有移动构造函数

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

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