17

我的问题很简单;

alignas 说明符是否与“新”一起使用?也就是说,如果一个struct被定义为对齐的,那么分配new时是否会对齐?

4

2 回答 2

16

在 C++17 之前,如果您的类型的对齐方式没有过度对齐,那么是的,默认值new将起作用。“过度对齐”表示您在 中指定的对齐方式alignas大于alignof(std::max_align_t)。默认值new将或多或少地与非过度对齐的类型一起使用;默认内存分配器将始终分配对齐等于alignof(std::max_align_t).

但是,如果您的类型的对齐方式过度对齐,那么您就不走运了。default 和您编写的new任何全局new运算符都无法知道类型所需的对齐方式,更不用说分配适合它的内存了。帮助这种情况的唯一方法是重载类的operator new,这将能够查询类与 的对齐alignof

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

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

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

于 2013-03-19T23:03:57.037 回答
15

不,不是的。该结构将被填充到请求的对齐位置,但不会对齐。然而,这有可能在 C++17 中被允许(这个 C++17 提案存在的事实应该很好地证明这在 C++11 中是行不通的)。

我已经看到这似乎适用于一些内存分配器,但这纯粹是运气。例如,一些内存分配器会将其内存分配与请求大小的 2 次方(最大 4KB)对齐,作为分配器的优化(减少内存碎片,可能更容易重用以前释放的内存等...) . 但是,我测试的 OS X 10.7 和 CentOS 6 系统中包含的 new/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;
}
于 2015-05-13T23:34:19.010 回答