保留后使用 std::vector::data
Posted
技术标签:
【中文标题】保留后使用 std::vector::data【英文标题】:Use std::vector::data after reserve 【发布时间】:2016-08-16 10:25:33 【问题描述】:我有一个std::vector
,我在上面调用reserve
,价值很大。然后我检索data()
。
由于迭代 data
会崩溃,我想知道这是否被允许。 reserve
是否强制更新 data
到分配的内存范围?
【问题讨论】:
为什么是reserve
而不是resize
? reserve
只分配内存,resize
在里面构造对象。
我们可以看看你的代码吗?
@n.m 调整大小可能非常昂贵。 Reserve 将保证您以后可以放置对象。
请注意,即使data()
有效并且在向量末尾之外分配了内存,您仍然无法保证您被允许访问该内存.例如可以想象,vector
实现将该内存用于簿记或其他目的。
这个问题:***.com/questions/25419851/…,讨论了在空向量上调用 data() 时会发生什么。 (你的向量是空的,因为 reserve() 不会改变大小。)似乎某些实现会返回一个 nullptr。
【参考方案1】:
reserve
的保证是后续插入不会重新分配,因此不会导致失效。就是这样。没有进一步的保证。
【讨论】:
这个保证是否适用于空向量?【参考方案2】:
reserve
是否强制将data
更新到分配的内存范围?
没有。标准只保证std::vector::data
返回一个指针并且[data(), data() + size())
是一个有效范围,capacity
不关心。
§23.3.11.4/1 vector data [vector.data]:
返回:一个使
[data(), data() + size())
有效的指针 范围。对于非空向量,data() == addressof(front())
。
【讨论】:
【参考方案3】:没有要求data()
为空 (size() == 0
) 向量返回可取消引用的指针,即使它具有非零容量。它可能会返回nullptr
或某个任意值(在这种情况下,唯一的要求是它应该能够与自身进行比较,并且可以在不调用 UB 的情况下添加 0)。
【讨论】:
【参考方案4】:我想说documentation 在这个主题上非常清楚:data() + size()
之后的任何内容都可能是分配但不是初始化内存:如果你也想初始化这个你应该使用vector::resize
的内存。
void reserve (size_type n);
请求更改容量
要求向量容量至少足以包含 n 个元素。
如果 n 大于当前向量容量,函数会导致 容器重新分配其存储,将其容量增加到 n (或更高)。
在所有其他情况下,函数调用不会导致重新分配 向量容量不受影响。
这个函数对向量大小没有影响,不能改变它的 元素。
我不知道为什么您首先要在reserve()
之后访问data() + size()
之后的任何内容:reserve()
的预期用途是在您知道或可以估计预期大小时防止不必要的重新分配您的容器,但同时避免不必要的内存初始化,这可能效率低下或不切实际(例如,用于初始化的重要数据不可用)。在这种情况下,您可以将 log(N)
重新分配和副本替换为仅提高 1 个性能。
【讨论】:
以上是关于保留后使用 std::vector::data的主要内容,如果未能解决你的问题,请参考以下文章
如何在Oracle数据库中保留小数点后两位 而且在java中保留两位插入到数据表中