在 C++ std::vector 和 C 数组之间转换而不复制

Posted

技术标签:

【中文标题】在 C++ std::vector 和 C 数组之间转换而不复制【英文标题】:Converting between C++ std::vector and C array without copying 【发布时间】:2010-12-16 12:43:57 【问题描述】:

我希望能够在 std::vector 及其底层 C 数组 int* 之间进行转换,而无需显式复制数据。

std::vector 是否提供对底层 C 数组的访问?我正在寻找这样的东西

vector<int> v (4,100)
int* pv = v.c_array();

编辑:

另外,是否可以反过来,即如何在不复制的情况下从 C 数组初始化 std::vector

int pv[4] =  4, 4, 4, 4;
vector<int> v (pv);

【问题讨论】:

这有一个“问题”: int pv[4] = 4, 4, 4, 4;向量 v (pv);它实际上将 pv 的内容复制到 v ...您只需要注意这一点 【参考方案1】:

你可以获得指向第一个元素的指针,如下所示:

int* pv = &v[0];

这个指针只有在向量没有被重新分配时才有效。如果您插入的元素多于向量的剩余容量(即v.size() + NumberOfNewElements &gt; v.capacity()),则会自动进行重新分配。您可以使用v.reserve(NewCapacity) 来确保向量的容量至少为NewCapacity

还要记住,当向量被销毁时,底层数组也会被删除。

【讨论】:

“只要你不向向量添加额外的元素” - 没有先保留空间。如果您reserve(),那么您可以将元素添加到您保留的容量,并保证引用和迭代器仍然有效。 @Steve:说得好。请确保在获得指针之前保留()! :) 反过来是不可能的; STL 容器管理自己的内存。您不能创建一个向量并让它管理您在其他地方分配的一些数组。将数组复制到向量中的最简单方法是使用std::vector&lt;int&gt; v(&amp;pv[0], &amp;pv[4]);,使用您添加到问题中的示例。 我认为向量没有消耗构造函数来让它拥有现有数组的所有权实际上太糟糕了。使与 C 库的互操作更加困难。 @JosephGarvin:array_ref&lt;T&gt; and string_ref&lt;T&gt; class templates 对此非常有帮助(两者都不是标准的——但我不知道任何具有这些确切接口的开源实现,但我有一个 @ Boost 许可的 CxxReflect 库中最有用的 987654322@)。【参考方案2】:

在c++11中,可以使用vector::data()获取C数组指针。

【讨论】:

【参考方案3】:
int* pv = &v[0]

请注意,这仅适用于std::vector&lt;&gt;,您不能对其他标准容器执行相同操作。

Scott Meyers 在他的书中广泛讨论了这个主题。

【讨论】:

“你不能对其他标准容器做同样的事情”-IIRC 你将能够在 C++0x 中使用字符串,实际上几乎每个实现都确实保证了字符串的存储是连续的。 您可以使用c_str()data() 成员获取包含std::string 元素的只读数组。正因为如此,虽然标准不要求字符串在内存中连续存储,但不这样做会非常奇怪且效率低下。 我假设标准设想的字符串可以实现为类似绳索的东西,因此附加和子字符串更快。访问会稍微慢一些(比如deque vs vector),并且c_str() 在第一次调用时会受到很大的惩罚。事实证明,实施者似乎都在权衡取舍,不想与它有任何关系...... 我也这么认为。当您编写可移植代码时,使用各种不同的常见和不那么常见的实现细节来编译和测试它,这将非常有用,超出了迂腐编译器的警告。但是看看当 C 编译器开始实际使用严格的别名规则时发生了什么 - 一半的代码中断,除了那种自鸣得意的标准律师之外,每个人都感到非常困惑 ;-) 真正学究气的程序员太少了能够使用这样的东西 - 你仍然有人建议在 gcc 上超过 -O2 是“危险的”......【参考方案4】:

如果你有非常可控的条件,你可以这样做:

std::vector<int> v(4,100);
int* pv = &v[0];

请注意,这仅在向量不必增长时才有效,并且向量仍将管理底层数组的生命周期(也就是说,不要删除 pv)。这在调用底层 C API 时并不少见,但通常使用未命名的临时变量而不是通过创建显式 int* 变量来完成。

【讨论】:

【参考方案5】:

保护自己免受尺寸变化的一种方法是保留您需要的最大空间(或更大):​​

std::vector<int> v(4,100); //Maybe need 
v.reserve(40);             //reallocate to block out space for 40 elements

这将确保 push_backs 不会导致现有数据的重新分配。

【讨论】:

以上是关于在 C++ std::vector 和 C 数组之间转换而不复制的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ std::vector 中删除元素

c++ 数组与 std::vector 和 std::array 的效率

C++ std::map 和 std::vector 的优点? [关闭]

在 C 和 C++ 中对齐堆数组以简化编译器 (GCC) 向量化

数组的 C++ 向量

C++中vector <int> array;如何像下面数组一样赋值