【问题标题】:Use std::vector::data after reserve保留后使用 std::vector::data
【发布时间】:2016-08-16 10:25:33
【问题描述】:

我有一个std::vector,我在上面调用reserve,价值很大。然后我检索data()

由于迭代 data 会崩溃,我想知道这是否被允许。 reserve 是否强制更新 data 到分配的内存范围?

【问题讨论】:

  • 为什么是reserve 而不是resizereserve 只分配内存,resize 在里面构造对象。
  • 我们可以看看你的代码吗?
  • @n.m 调整大小可能非常昂贵。 Reserve 将保证您以后可以放置对象。
  • 请注意,即使data() 有效并且在向量末尾之外分配了内存,您仍然无法保证您被允许访问该内存.例如可以想象,vector 实现将该内存用于簿记或其他目的。
  • 这个问题:stackoverflow.com/questions/25419851/…,讨论了在空向量上调用 data() 时会发生什么。 (你的向量是空的,因为 reserve() 不会改变大小。)似乎某些实现会返回一个 nullptr。

标签: c++ vector language-lawyer stdvector


【解决方案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 个性能。

      【讨论】:

        猜你喜欢
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        • 2016-05-23
        • 2017-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多