【问题标题】:Is using std::span into an std::vector after push_back is called undefined behavior在 push_back 被称为未定义行为之后,将 std::span 用于 std::vector
【发布时间】:2021-12-07 11:17:13
【问题描述】:

我对@9​​87654322@的理解是,它本质上包含指向容器的指针、大小和一些有用的成员函数。

template<typename T>
class SimpleSpan {
    T* ptr;
    size_t length;
    // some member functions
}

我可以取一个向量的跨度,如 this question 所示。

如果我在向量的末尾添加条目,则可能需要调整向量的大小。调整矢量大小时,会发生以下步骤(顺序不重要)。

  1. 在具有更多空间的堆上分配一个新数组。

  2. 向量中的条目被移动到新数组中。

  3. vectorvector 的数组的成员ptr 更改为新数组的开头。

  4. 旧数组被释放。

如果vector 的数组需要重新分配并变大,span 会发生什么事情吗?在 push_backvector 未定义行为调用之后,是否将 span 用于 vector

【问题讨论】:

  • push_back 可能使其元素的指针、引用和迭代器无效。仅当push_back 必须增加capacity 时才会发生这种情况。如果capacity() &gt; size()push_back 之前,则span 将保持有效。
  • resize 不一定是重新分配,只有在容量不够时才需要重新分配,尽管它只是措辞上的挑剔

标签: c++ vector undefined-behavior ownership-semantics std-span


【解决方案1】:

我对 std::span 的理解是,它本质上包含指向容器的指针、大小和一些有用的成员函数。

这不是相当正确的。 std::span 完全忽略了数据所在的位置。它只处理数据本身。属于容器的数据的性质(甚至概念)被完全抹去。它所关心的只是数据在内存中是连续的。

因此,如果一个向量曾经调整大小,这可能发生在push_back() 期间。数据可能被移动到不同的内存位置,从而使指向它的任何指针无效。这反过来又会使引用该数据的任何std::span 无效。

【讨论】:

    【解决方案2】:

    push_back 上的文档内容如下:

    如果新的 size() 大于 capacity(),则所有迭代器和引用(包括过去的迭代器)都将失效。否则只有过去的迭代器无效。

    那里有您的答案:如果必须调整矢量大小,您通过旧跨度的访问将无效。如果没有,就不会。

    【讨论】:

      猜你喜欢
      • 2023-02-07
      • 2013-10-15
      • 2021-03-02
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 2021-12-02
      • 2017-09-21
      • 2021-06-18
      相关资源
      最近更新 更多