在std::vector中就地构造一对不可移动、不可复制的

In place construction of a pair of nonmovable, non copyable in a std::vector

假设以下不可复制且不可移动的结构 X 没有默认构造函数且没有单个参数构造函数:

struct X
{
    X(int x, int y) { }
    X(const X&) = delete;
    X(X&&) = delete;
};

和一个向量 std::vector<pair<X,X>> v。要插入到 v 中,可以使用 emplace_back 如果 X 仅可从一个参数构造,因为它有效地调用了 std::pair<X,X> 的构造函数。 我们可以这样做:

v.emplace_back(X(42,42),X(69,69));

但在这种情况下, X 的移动构造函数被调用,后者无法编译。由于这是不可能的,我们必须使用 std::pair 的 std::piecewise_construct 构造函数并调用:

v.emplace_back(std::piecewise_construct, std::forward_as_tuple(42,42), std::forward_as_tuple(69,69));

我希望它能正常工作,但出于某种原因,向量正在调用 move ctor(或复制,如果只删除 move)。

例如将容器更改为 std::list,一切正常。将 < 运算符添加到 X 并创建 std::map<X,X>(具有成对的 X 作为节点)或 std::set<std::pair<X,X>> 并使用 emplace 而不是 emplace_back 一切似乎都有效。 std::vector 有什么问题?

可以找到完整的代码片段 here

一旦大小达到容量,

std::vector 将重新分配。 当将元素重新分配到新的内存段时,std::vector 必须 copy/move 来自旧段的值,这是通过调用 copy/move 构造函数实现的。

如果您不需要元素在内存中是连续的,您可以使用 std::deque,因为 std::deque 不会在内部重新分配元素。

您不能将不可复制和不可移动的对象存储到 std::vectors 中。


@François Andrieux 建议编辑

如果出于任何原因您仍然需要 std::vector,您可能会考虑使用使用 std::unique_ptr<X> 作为 值类型 使用 [=16] 制作的向量=].

使用此解决方案,您仍然无法在内存中获得元素的顺序,并且它们会一直保存在内存中,直到它们仍在向量中,所以除非您出于任何原因被迫使用 std::vectors,我认为最好的匹配仍然是 std::deque.