部分 std::move 一个矢量?或者如何在没有新内存分配的情况下拆分?

Partially std::move a vector? Or how to split without new memory allocation?

当我们移动 std::vector 时,我们只是窃取了它的内容。所以这段代码:

std::vector<MyClass> v{ std::move(tmpVec) };

不会分配新内存,不会调用MyClass的任何构造函数。

但是如果我想拆分一个临时向量怎么办?理论上,我可以像以前一样窃取内容并将其分发给新的向量。实际上我不能这样做。迄今为止我发现的最佳解决方案是使用 <algorithm> header 中的 std::move()。但是这里将为每个新向量调用 operator new 。此外,移动构造函数(如果可用)将为我们移动的每个元素调用。

我还能做什么(c++17 计数)?

In theory, I could steal the content as we did before and distribute it among new vectors.

不,你不能。

一个内存分配不能分解为多个内存分配。至少,不是没有做多次内存分配,然后 copying/moving 将元素从原来的分成几块。

您不能创建具有不同存储空间的单独 vectors,而实际上 copying/moving 元素到这些不同的内存缓冲区。您当然可以采用 vector 的单独范围,并使用这些范围(iterator/pointer 对、gsl::span 等)做任何您能做的事情。但是每个范围总是引用最终归源vector所有的元素;他们不能独立拥有 vector.

的子范围

你可以写一个 span class 来存储两个指针,并且不拥有它们之间的数据。它可以有很多类似矢量的操作。

它还应该支持将自身切片(无需分配)为子组件。

您可以编写一个 shared_span class 来同时具有这两个指针,以及一个 shared_ptr 来表示(可能是共享的)底层缓冲区的所有权。它应该支持 span 的操作,除了函数 returning span(如 without_front(std::size_t count=1))应该改为 return shared_span(共享所有权) .

您可以轻松编写从 vectorshared_span 的移动构造函数。您甚至可以使用一个特殊的分配器编写一个从 shared_spanvector 的函数,该分配器在它增长之前不会分配。使其完全便携将非常困难。

如果可能(我不确定),你可以使用 std::vector,将其存储移动到 shared_ptr<std::vector>,将其提供给分配器,构建两个 std::vector<T, special_allocator>使用那个内存,做你想做的事。

但是您可以只用消耗 shared_span 的代码替换您对 vector 的请求。 shared_span 甚至可以有额外 "dead" 内存的概念 before/after 它正在使用的缓冲区,使其性能接近 std::vector.

gsl 库中有一个您可以使用的跨度。我不知道公开可用 shared_span.