【问题标题】:Partially std::move a vector? Or how to split without new memory allocation?部分 std::move 一个向量?或者如何在没有新内存分配的情况下拆分?
【发布时间】:2017-08-19 10:33:17
【问题描述】:

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

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

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

但是如果我想拆分一个临时向量怎么办?理论上,我可以像以前一样窃取内容并将其分发到新的向量中。在实践中我不能这样做。迄今为止我发现的最好的解决方案是使用来自&lt;algorithm&gt; 标头的std::move()。但是这里每个新向量都会调用operator new。此外,将为我们移动的每个元素调用移动构造函数(如果可用)。

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

【问题讨论】:

    标签: c++11 move move-semantics


    【解决方案1】:

    理论上,我可以像以前一样窃取内容并将其分发到新的向量中。

    不,你不能。

    一个内存分配不能分成多个内存分配。至少,不是不进行多次内存分配,然后将元素从原始元素复制/移动到这些单独的片段中。

    如果不将元素实际复制/移动到这些不同的内存缓冲区,则无法创建具有不同存储空间的单独 vectors。当然,您可以使用该 vector 的单独范围,并使用这些范围(迭代器/指针对、gsl::span 等)做任何可以做的事情。但是每个范围总是引用源 vector 最终拥有的元素;他们不能独立拥有vector 的子范围。

    【讨论】:

    • 理论上,我的意思是:向量基本上是一对指向内存开始和结束的指针。所以理论上,我们可以指定任何指针作为从这个范围到新向量的开始/结束,而无需分配。当然,旧的应该作废。我看不出我们不能这样做的原因(再次——理论上。因为神圣的标准没有提供这样做的方法)。
    • "一个内存分配不能分成多个内存分配。" - 这让我很困惑。为什么不呢?
    • @nikitablack:但是您正在创建的vector 会为自己分配内存。 vector的两个迭代器构造函数没有adopt给定内存;它分配自己的内存。
    • @nikitablack: "再次——理论上。因为神圣标准没有提供这样做的方法" 如果标准不允许,那么它不是有效的理论。如果你问vector能做什么,那么它首先要做的就是符合标准。否则,它不是vector。如果您要问vector like 类型可以做什么,那就是另一个问题了。答案仍然是“不”,但原因更复杂。
    • 是的,你是对的。问题是我能做些什么来窃取一部分记忆。但现在我看到,即使我能做到,另一部分也应该被释放,这是不可能的。伤心,但是,我接受你的“No, you cannot”回答。谢谢。
    【解决方案2】:

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

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

    您可以编写一个具有这两个指针的shared_span 类,以及一个代表(可能共享的)底层缓冲区所有权的shared_ptr。它应该支持span 的操作,除了返回span 的函数(如without_front(std::size_t count=1))应该返回shared_span(共享所有权)。

    您可以轻松编写从vector 到shared_span 的移动构造函数。您甚至可以使用特殊分配器编写从shared_span 到vector 的函数,该分配器在增长之前不会分配。实现完全便携是非常困难的。

    如果可能(我不确定),您可以使用std::vector,将其存储移动到shared_ptr&lt;std::vector&gt;,将其提供给分配器,构建两个使用该内存的std::vector&lt;T, special_allocator&gt;s,然后执行你想要的。

    但是您可以将您对 vector 的请求替换为使用 shared_span 的代码。 shared_span 甚至可以在它使用的缓冲区之前/之后有一个额外“死”内存的概念,使其性能接近std::vector。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-28
      • 2021-12-02
      • 1970-01-01
      相关资源
      最近更新 更多