如何在不导致复制的情况下将 char 数据附加到 std::vector

Posted

技术标签:

【中文标题】如何在不导致复制的情况下将 char 数据附加到 std::vector【英文标题】:How to append char data to a std::vector without causing a copy 【发布时间】:2019-06-24 10:26:37 【问题描述】:

我有一个包含一些数据元素的字符向量。

std::vector<unsigned char> data_1;

我有一个 unsigned char * 指向另一组数据元素。

unsigned char * data_2;

问题: 有没有办法可以将 data_2 合并到 data_1 中,这是一个向量,而不会导致数据元素的副本?

我在this discussion 中读到了有关移动语义的信息,但我有点不确定在这种情况下是否可行。

【问题讨论】:

【参考方案1】:

有没有一种方法可以将 data_2 合并到作为向量的 data_1 中,而不会导致数据元素的副本?

没有。将元素插入向量的所有方式都需要至少复制(或移动)每个元素一次。

我读到了这个讨论中提到的移动语义,但我有点不确定在我这里遇到的这种情况下是否可行。

移动字符与复制字符相同。区别仅与具有非平凡移动构造函数或移动赋值运算符的类类型有关。

即使 data_2 是 std::vector&lt;unsigned char&gt; 也不可能?

Appending 即使在那时也不可能不复制(或移动)。

旁注 1:您可以使用向量的移动赋值运算符替换一个向量的全部内容与另一个向量的内容,而无需复制(或移动)任何元素。

旁注 2:您可以合并两个基于节点的容器实例,例如 std::lists、std::sets、std::maps 及其无序对应物,而无需复制(或移动)任何元素。

【讨论】:

【参考方案2】:

不,你不能那样做。

矢量数据是连续存储的,因此除非您的缓冲区已经以某种方式背靠背(它们不是),否则至少需要移动其中一个(读取:复制)

向量不能拥有现有内存的所有权(你的unsigned char* data_2

向量不能同时拥有两个内存块(假设std::vector&lt;unsigned char&gt; data_2

但是,您可以在使用时将其设置为 这无关紧要 having a single iterator type "jump" from the first buffer to the second, transparently。

【讨论】:

感谢您的快速回复。即使data_2std::vector&lt;unsigned char&gt; 也不可能吗?我知道这仍然不可能,但希望确认一次。 @AdeleGoldberg:不(尽管至少第二个要点不会[直接]适用)【参考方案3】:

没有。 vectors 连续存储;虽然您可以避免在填充data_1 之前通过reserve 为连接数据的完整大小提供足够的空间来重新分配data_1,但您无法避免字节的实际副本;数据必须移动到与data_1 中现有数据相邻的位置,vector 无法避免。

【讨论】:

【参考方案4】:

是的,你可以。但是你必须为向量定制分配器。

默认情况下,vector 使用std::allocator,您可以使用vector::get_allocator 来获取分配器对象。您可以尝试使用allocator::construct 方法进行一些操作(我没有深入研究)。

当您实例化 vector 时,您可以将自定义分配器传递给向量,这将有助于使用已分配的内存(placement new)或任何其他内存分配函数。 This article 可能会有所帮助。

但是,我认为这样的努力并不真正有成果。

【讨论】:

是否可以编写一个分配器来提供对 两个 独立内存块的访问,就像它们是一个一样?

以上是关于如何在不导致复制的情况下将 char 数据附加到 std::vector的主要内容,如果未能解决你的问题,请参考以下文章

如何在不跟踪索引的情况下将元素附加到列表?

如何在不删除旧文档的情况下将 XMLDocument 附加到 LocalStorage

如何在不覆盖数据源参数的情况下将附加参数传递给剑道模板

无法在不覆盖的情况下将 R 数据框附加到现有 Excel 中

在不删除原始 UserDefault 信息的情况下将数组附加到 UserDefaults

如何在不跟踪索引的情况下将元素附加到列表中?