部分 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 将元素从原来的分成几块。
您不能创建具有不同存储空间的单独 vector
s,而实际上 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
(共享所有权) .
您可以轻松编写从 vector
到 shared_span
的移动构造函数。您甚至可以使用一个特殊的分配器编写一个从 shared_span
到 vector
的函数,该分配器在它增长之前不会分配。使其完全便携将非常困难。
如果可能(我不确定),你可以使用 std::vector
,将其存储移动到 shared_ptr<std::vector>
,将其提供给分配器,构建两个 std::vector<T, special_allocator>
使用那个内存,做你想做的事。
但是您可以只用消耗 shared_span
的代码替换您对 vector
的请求。 shared_span
甚至可以有额外 "dead" 内存的概念 before/after 它正在使用的缓冲区,使其性能接近 std::vector
.
gsl
库中有一个您可以使用的跨度。我不知道公开可用 shared_span
.
当我们移动 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 将元素从原来的分成几块。
您不能创建具有不同存储空间的单独 vector
s,而实际上 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
(共享所有权) .
您可以轻松编写从 vector
到 shared_span
的移动构造函数。您甚至可以使用一个特殊的分配器编写一个从 shared_span
到 vector
的函数,该分配器在它增长之前不会分配。使其完全便携将非常困难。
如果可能(我不确定),你可以使用 std::vector
,将其存储移动到 shared_ptr<std::vector>
,将其提供给分配器,构建两个 std::vector<T, special_allocator>
使用那个内存,做你想做的事。
但是您可以只用消耗 shared_span
的代码替换您对 vector
的请求。 shared_span
甚至可以有额外 "dead" 内存的概念 before/after 它正在使用的缓冲区,使其性能接近 std::vector
.
gsl
库中有一个您可以使用的跨度。我不知道公开可用 shared_span
.