std::vector::reserve 是不是重新分配内部数组?
Posted
技术标签:
【中文标题】std::vector::reserve 是不是重新分配内部数组?【英文标题】:Does std::vector::reserve reallocate the internal array?std::vector::reserve 是否重新分配内部数组? 【发布时间】:2012-03-04 14:36:49 【问题描述】:我有一个函数,它接受int *
并修改传入的数组。我提前知道它将访问多少个元素。假设这是m
值。
如果我在 vector<int>
上调用 reserve(m)
然后将指针 data()
发送到函数会发生什么?
我的猜测是,如果我随后从指针访问数据,就好像它是一个数组一样,那么这样做 可能 工作,但是如果我尝试使用 @ 从向量中检索这些数据987654326@ 向量的大小不会更新,我会有问题。所以我应该只使用resize(m)
来做到这一点。
【问题讨论】:
你能给我们看一些代码而不是解释代码的作用吗? 我会说你的猜测是正确的,只需使用resize
。
为什么你想这样做?
是的,使用 resize()。你为什么还要问这个,你看到 resize() 有什么缺点吗?
data()
不是std::vector
(2003 标准)的一部分
【参考方案1】:
不要这样做;这是未定义的行为,根本不允许。相反,您应该执行几乎同样昂贵的resize()
操作,然后传递data()
指针。
唯一增加的成本来自内存的归零。不幸的是,没有标准库容器可以处理 未初始化 动态存储,而不是 std::unique_ptr<int[]>(new int[m])
。不过,归零的成本非常小(但它在概念上可能很烦人,因为您知道您将覆盖数据)。我想在高性能环境中,您可以尝试使用唯一指针方法。 (请注意,基本类型的数组-new[]
通常完全等同于::operator new()
或malloc()
)。
【讨论】:
【参考方案2】:正确,空向量上的reserve(m)
只是保证下一个 m push_back()
不会触发重新分配。向量的大小仍将保持为 0,并且禁止写入分配的数据。
这里调用resize(m)
是正确的方法。
【讨论】:
【参考方案3】:void reserve ( size_type n );
只有在当前容量小于n时才重新分配内部数组。
【讨论】:
【参考方案4】:reserve
改变了容器的内部大小(因此capacity()
现在更大了),但数组的size
没有增长(size()
保持与调用之前相同)。因此,要直接回答您的问题,是,它使向量的capacity
至少为n
,其中n
是您提供给reserve
的参数。
如果capacity
足够大(但size
更小),当您调用data()
时(或执行@ 987654333@) 并通过该指针访问数组。只要您在向量中使用 POD 类型并且在写入它们之前不读取它们,我认为这不会是未定义的行为。但是不要尝试使用类类型,因为向量的 size
之外的元素将未初始化,并且使用它们将是 UB。
这样做是没有意义的,因为当你尝试push_back
向量上的某些东西或调用resize
来实际更新大小时,它会覆盖你颠覆性地写入向量的值。只需使用resize
或使用vector(int)
构造函数来设置构造大小。
【讨论】:
它应该是未定义的。size()
之后的那些元素不会被初始化。
@James 他说他正在使用vector<int>
(POD),所以只要他在写入值之前不读取值,他应该没问题,不是吗?
不,我们说的是未调整大小的向量。无论存储的模板类型如何,引用(读取或写入)向量末尾之外的任何元素都是未定义的。 (有效地解除对 end() + n 的引用,其中 n >= 0。)虽然它可能“有效”,但这绝对不是一个好习惯。
@James 我认为不好的做法和未定义的行为不是一回事。这是否是一种好的做法是相当明显的(不是),但我认为这不会使它成为未定义的行为。
老实说,刚刚花了最后 20 分钟浏览 C++ 标准,我不知道它是否未定义。我的直觉仍然认为它是,或者如果不是,它应该是。访问向量内存的唯一方法是通过&*
,它创建一个指针,显然如果您知道内存是有效的,那么递增和取消引用该指针就不是未定义的。然而,事实上它是通过取消引用迭代器获得的指针,这里有一个略带灰色的区域:( &*begin() ) + n
不是未定义的,但&*( begin() + n )
是(其中 n >= size() 和 n
以上是关于std::vector::reserve 是不是重新分配内部数组?的主要内容,如果未能解决你的问题,请参考以下文章
std::vector::resize() 与 std::vector::reserve()
libxx.so: undefined reference, vector.reserve(n)
libxx.so: undefined reference, vector.reserve(n)