【问题标题】:Is it possible to emplace a std::array in a container? If it is how? If not, why? [duplicate]是否可以在容器中放置一个 std::array ?如果是怎么回事?如果不是,为什么? [复制]
【发布时间】:2021-03-03 09:31:24
【问题描述】:

给定简单的代码

#include <array>
#include <vector>
int main() {
    std::vector<std::array<int,3>> v;
    v.emplace_back(std::array<int,3>{1,2,3});
}

我首先担心到底发生了什么。

我对 emplace_back 的理解是,它通过将其参数转发到该元素的构造函数。

但是哪个构造函数?由于我们传递的是与我们想要放置的元素类型相同的对象,我猜想选择了移动构造函数,因为我们传递的是临时的,或者如果移动 ctor 被删除(隐式或显式),则传递复制 ctor。此外,我们首先是在构建那个临时的,而这没有就地完成,对吧?

所以我们基本上是通过将123 作为参数传递给std::array&lt;int,3&gt; 的“普通”(???) 构造函数,从而取回一个临时的,它被传递到std::array&lt;int,3&gt; 的复制ctor,它在适当的位置构造副本,或者最好是到std::array&lt;int,3&gt; 的移动ctor,它(?)复制底层C 样式指针?

应该清楚这个简单的例子让我很困惑。

更让我困惑的是,如果我真的想利用emplace_back,我只能将std::array&lt;int,3&gt; 的参数传递给它,如

#include <array>
#include <vector>
int main() {
    std::vector<std::array<int,3>> v;
    v.emplace_back(1,2,3);
}

which doesn't even compile.

【问题讨论】:

  • std::array 没有用户定义的构造函数。它使用聚合初始化。
  • stackoverflow.com/q/43394841/103167 的副本(另一个问题中的“结构”和您的 std::array 都是需要聚合初始化的聚合)。

标签: c++ c++11 stdarray emplace


【解决方案1】:

让我试着澄清一下。首先,std::array&lt;&gt; 是一个aggregate。它根本没有任何用户定义的构造函数。

所以它是准可移动的(技术术语是trivially movable),这意味着您可以从临时构造它,但它会简单地复制底层数组。所以代码最终要做的是将提供的数组复制到新分配的向量元素中。

如果您将emplace_back 替换为push_back,您将获得相同的结果(但输入会稍微减少),如下所示:

    v.push_back({1,2,3});

emplace_back(1, 2, 3) 无法编译,因为std::array&lt;&gt; 没有任何构造函数接受多个参数。

【讨论】:

  • 为什么在使用临时std::array 构造std::array 时需要完整的副本?不能从临时对象中窃取指针到正在创建的对象吗?
  • @Enrico std::array 没有可窃取的指针,因为它不管理动态分配的内存。这是std::array&lt;&gt;std::vector&lt;&gt; 之间的主要区别。
  • 哦,当然!只是std::vector&lt;T&gt;里面有一个T * ptr;ptr是一个可修改的左值,而std::array&lt;T,N&gt;里面有一个T arr[N];,这是一个不可修改的左值。
  • 在 C++20 中 emplace_back 可以初始化聚合,但仍然不能初始化 std::array,所以它们有本质的不同。
  • @Fedor 你能澄清你的评论吗?
猜你喜欢
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
相关资源
最近更新 更多