如何使用指向自定义分配器(无 UB)提供的原始内存的指针?

How to work with pointers into raw memory provided by custom allocators (without UB)?

我正在尝试编写一个分配器感知容器。假设我想为三个对象分配一块内存:

T* chunk = std::allocator_traits<Allocator>::allocate(allocator, 3);

(我知道分配器可以有自定义指针类型,因此我应该使用 std::allocator_traits<Allocator>::pointer;为了简单起见,我在这里使用原始指针。)

现在我想在索引 2 处创建一个实际对象。我该怎么做?特别是,如何计算指向尚不存在的元素的指针?最明显的选择如下:

std::allocator_traits<Allocator>::construct(allocator, chunk + 2, ...);

不幸的是,chunk + 2 似乎不正确:according to the standard,指针运算只能在指向数组元素的指针上执行,否则会导致未定义的行为。出于同样的原因,我无法将指针转换为 std::byte* 并对其使用指针算法。 (虽然 std::allocator 被定义为在新分配的内存中创建一个数组,但在 C++20 之前,自定义分配器不存在相同的要求。此外,虽然 C++20 添加了一些用于“隐式创建对象”的语言”,这不适用于早期的 C++ 版本。)

那么我如何计算指针以作为 construct 的第二个参数给出而不导致未定义的行为(在 C++20 之前)?

在最新的标准草案(C++20)中:

[tab:cpp17.allocator]

a.allocate(n) - Memory is allocated for an array of n T and such an object is created but array elements are not constructed.

allocator_traits::allocate(n) 只是调用 a.allocate(n).

所以,既然创建了数组,那么指针算法就定义好了。


在接受提案P0593R6之前的C++17中,写法是:

Memory is allocated for n objects of type T is created but objects are not constructed.

在此更改之前,没有 well-defined 方法可以满足您的要求,除非:

  • 我们假设自定义分配器提供创建此类数组的保证。问题是没有标准的方法可以在不创建对象的情况下创建数组(没有默认分配器),因此没有标准的方法来实现这种自定义分配器。
  • 我们忽略了指针运算的限制。理论上的问题是未定义的行为。实际上,这并不是实际语言实现的问题。