在C ++中分配和使用具有动态指定对齐方式的缓冲区的正确方法是什么?我想到的用例是Vulkan动态统一缓冲区(请参见this previous question,该缓冲区抽象地讨论了所需的过程),针对对齐的约束是通过minUniformBufferOffsetAlignment
的VkPhysicalDeviceLimits
属性给出的,在编译时已知。
我最初以为我可以使用operator new(std::align_val_t)
做类似的事情
Foo* buffer = new(std::align_val_t{alignment}) Foo[n];
但是不会编译(至少在MSVC上)。
[我也看过Timur Doumler的CppCon演示文稿“ Type punning in modern C++”,它指出,对reinterpret_cast
之类的结果使用std::aligned_alloc
会导致不确定的行为。
到目前为止,我已经提出了以下内容:
std::size_t n = getNumberOfElements(); // possibly not known at compile time
std::size_t alignment = getRequiredAlignment(); // not known at compile time
void* storage = std::aligned_alloc(sizeof(Foo[n]), alignment); // _aligned_malloc on MSVC
Foo* buffer = new(storage) Foo[n];
// do stuff with buffer
for(std::size_t i = 0; i < n; ++i) { buffer[i].~Foo(); }
std::free(storage); // _aligned_free on MSVC
我在这里错过了会导致不确定行为的东西吗?
Foo[n]
是一个可变长度的数组,它们不是标准C ++的一部分。您可以在不使用VLA的情况下执行以下操作:
Foo* storage = static_cast<Foo*>(std::aligned_alloc(n * sizeof(Foo), alignment));
std::uninitialized_default_construct_n(storage, n);
// ...
std::destroy_n(storage, n);
free(storage);