没有未定义行为的 C++ 中的动态数组

Naz*_*nho 3 c++ arrays undefined-behavior language-lawyer

在了解到 std::vector 在纯 C++ 中无法实现后,我想知道是否可以在不调用 UB 的情况下编写动态数组。我们不能在没有数组的情况下进行指针运算,这意味着我们不能有一个带有部分初始化内存的动态缓冲区并将其视为数组;所以 std::vector 必须依赖于定义一些行为的实现,否则它会是 UB。

动态数组是非常普遍的数据结构,而且通常很简单。能够一致地实现这一点似乎是不可能的,这使得 C++ 看起来像是一种不太通用的系统语言,IMO。

因此,我的问题是:

  • 如何用 C++(不使用 std::vector)编写符合标准的动态数组(普通数组,不一定是容器)?
  • 如何使这种实现具有时空效率(最好没有 UB 或实现特定的行为)?

注意:这里使用动态数组来表示可以“就地”增长/收缩的线性数据结构,如 std::vector 或类似地,在堆中分配的 C 缓冲区 (m)。

Ast*_*ngs 7

如果std::vector不能,那么你也不能。

但我不会担心。这是人们发现标准措辞有问题的情况之一,从技术上讲,这使得非常常见的用例未定义。但是你的向量仍然有效。

现在,关键是:这不是因为天生的魔法std::vector,或某些特定的std::vector实现:这是因为编译器不会执行荒谬的优化来利用这种未定义的行为,有人只是在用细齿的方式研究文本时才发现这种行为梳子。

也许它会在未来的修订版中进行整理,但出于实际目的,您无需担心它,无论您使用std::vector还是使用new[].


Nic*_*las 5

这里使用动态数组来表示可以“就地”增长/收缩的线性数据结构,

你不能。正是就地增长/收缩使vectorC++17 无法实现。

问题在于 C++17 对象模型将“数组”识别为一种事物,一种具有自己属性的特殊对象类型。指针算术识别数组并在其中工作。但是“数组”具有特定的元素计数,仅在数组末尾创建数组元素类型的活动对象实际上并不会使数组变长。这意味着指针算法无法访问这个新创建的对象。

该问题不会因为您更改包装器而消失。这是一个问题,对于能够使数组变得越来越大,同时仍然进行指针算术工作的想法至关重要。