【问题标题】:std::vector emplace_back() for non copy constructible objectsstd::vector emplace_back() 用于不可复制的可构造对象
【发布时间】:2014-05-24 05:02:22
【问题描述】:

考虑到来自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(const A &)' : 试图引用已删除的函数

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

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

【问题讨论】:

  • std::vector 要求其包含的类型是可复制构造的。它没有解释为什么单个 emplace_back 会失败,但你会在某些时候遇到麻烦。
  • @heinrichj move-constructible.
  • @Angew 感谢您的更正;无论哪种方式,Visual C++ 目前都不支持隐式定义的移动构造函数,所以至少你仍然不走运。

标签: c++ c++11 vector


【解决方案1】:

C++11 23.2.1 表 101 状态:

表达式:a.emplace_back(args)

返回类型:void

操作语义:追加使用std::forward&lt;Args&gt;(args)... 构造的T 类型的对象。 要求: T 应从 args 变为 EmplaceConstructibleX。对于vectorT 也应将MoveInsertable 转换为X

您的A 不满足MoveInsertable 的要求,因为您没有移动构造函数,而只有一个已删除的复制构造函数。使用std::vectorit works以外的容器。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2014-09-14
      • 2013-06-05
      • 1970-01-01
      • 2012-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多