在某些用例中,您需要先分配存储空间,然后再在此存储中创建对象。
然后为了创建这些对象,您可能需要使用placement new:
T *pobj = new(pstorage);
但是您必须提供正确对齐的
pstorage
。
AFAIU 以下代码不提供过度对齐类型的保证。
// properly aligned heap storage to hold N contiguous T objects
unsigned char *storage = new unsigned char[N*sizeof(T)];
operator new
过度对齐类型的重载似乎无法明确使用(https://stackoverflow.com/a/78679166/21691539)。
到目前为止我发现的最简单的解决方案是:
// in the spirit of std::aligned_storage
// can be on the stack or on the heap
template <typename T, std::size_t N>
struct Storage {
alignas(T) unsigned char storage[N * sizeof(T)];
}
auto *wrapped_storage = new Storage<T,N>;
auto *storage = wrapped_storage.storage;
但只有在编译时已知对象数量时它才有效。
使原始存储适当对齐过度对齐类型的正确方法是什么?
从 C++17 开始:
// properly aligned heap storage to hold N contiguous T objects
unsigned char *storage = std::aligned_alloc(alignas(T),N*sizeof(T));
...
// releasing memory
std::free(storage);
用于在位置
i
创建非隐式生命周期对象的代码片段:
// placement-new
new(storage+i*sizeof(T)) T(<constructor args>);
...
// destroying non-trivially destructible object is mandatory before releasing storage
T* toDelete = std::launder(reinterpret_cast<T*>(storage+i*sizeof(T)));
toDelete->~T(); // destroy object but don't deallocate memory
这只是一个低级示例,使用智能指针进行更智能的实现会更好。