对齐说明符是否适用于"新"?

Does the alignas specifier work with 'new'?

本文关键字:适用于 说明符 是否 对齐      更新时间:2023-10-16

我的问题很简单;

对齐说明符是否与'new'一起工作?也就是说,如果一个结构体被定义为对齐,那么在分配new时它会对齐吗?

在c++ 17之前,如果你的类型的对齐方式没有过度对齐,那么是的,默认的new将工作。"Over-aligned"表示您在alignas中指定的对齐大于alignof(std::max_align_t)。默认的new将或多或少偶然地与非过度对齐类型一起工作;默认内存分配器将始终以等于alignof(std::max_align_t)的对齐方式分配内存。

如果你的字体对齐过度,你就倒霉了。无论是默认的new,还是您编写的任何全局new操作符,都无法知道该类型所需的对齐方式,更不用说为其分配合适的内存了。帮助这种情况的唯一方法是重载类的operator new,它将能够查询类与alignof的对齐。

当然,如果这个类被用作另一个类的成员,这就没有用了。除非其他类也重载operator new。所以像new pair<over_aligned, int>()这样简单的东西是行不通的。

c++ 17增加了一些内存分配器,这些分配器被赋予了所使用类型的对齐方式。这些分配器专门用于过度对齐类型(或者更具体地说,新扩展的过度对齐类型)。所以new pair<over_aligned, int>()将在c++ 17中工作。

当然,这只适用于分配器处理过对齐类型的情况。

不,它没有。结构体将被填充到请求的对齐方式,但它不会被对齐。然而,这有可能在c++ 17中被允许(这个c++ 17提案存在的事实应该很好地证明了这在c++ 11中不能工作)。

我已经看到这似乎与一些内存分配器工作,但那纯粹是运气。例如,一些内存分配器会将它们的内存分配对齐到请求大小的2次方(最多4KB),作为对分配器的优化(减少内存碎片,可能更容易重用以前释放的内存,等等……)。但是,我测试的OS X 10.7和CentOS 6系统中包含的新的/malloc实现不会这样做,并且会出现以下代码失败:

#include <stdlib.h>
#include <assert.h>
struct alignas(8)   test_struct_8   { char data; };
struct alignas(16)  test_struct_16  { char data; };
struct alignas(32)  test_struct_32  { char data; };
struct alignas(64)  test_struct_64  { char data; };
struct alignas(128) test_struct_128 { char data; };
struct alignas(256) test_struct_256 { char data; };
struct alignas(512) test_struct_512 { char data; };
int main() {
   test_struct_8   *heap_8   = new test_struct_8;
   test_struct_16  *heap_16  = new test_struct_16;
   test_struct_32  *heap_32  = new test_struct_32;
   test_struct_64  *heap_64  = new test_struct_64;
   test_struct_128 *heap_128 = new test_struct_128;
   test_struct_256 *heap_256 = new test_struct_256;
   test_struct_512 *heap_512 = new test_struct_512;
#define IS_ALIGNED(addr,size)   ((((size_t)(addr)) % (size)) == 0)
   assert(IS_ALIGNED(heap_8, 8));
   assert(IS_ALIGNED(heap_16, 16));
   assert(IS_ALIGNED(heap_32, 32));
   assert(IS_ALIGNED(heap_64, 64));
   assert(IS_ALIGNED(heap_128, 128));
   assert(IS_ALIGNED(heap_256, 256));
   assert(IS_ALIGNED(heap_512, 512));
   delete heap_8;
   delete heap_16;
   delete heap_32;
   delete heap_64;
   delete heap_128;
   delete heap_256;
   delete heap_512;
return 0;
}