如何使用指向自定义分配器(无 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 方法可以满足您的要求,除非:
- 我们假设自定义分配器提供创建此类数组的保证。问题是没有标准的方法可以在不创建对象的情况下创建数组(没有默认分配器),因此没有标准的方法来实现这种自定义分配器。
- 我们忽略了指针运算的限制。理论上的问题是未定义的行为。实际上,这并不是实际语言实现的问题。
我正在尝试编写一个分配器感知容器。假设我想为三个对象分配一块内存:
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 方法可以满足您的要求,除非:
- 我们假设自定义分配器提供创建此类数组的保证。问题是没有标准的方法可以在不创建对象的情况下创建数组(没有默认分配器),因此没有标准的方法来实现这种自定义分配器。
- 我们忽略了指针运算的限制。理论上的问题是未定义的行为。实际上,这并不是实际语言实现的问题。