Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ alignas说明符是否与';新的';?_C++_C++11_New Operator_Memory Alignment - Fatal编程技术网

C++ alignas说明符是否与';新的';?

C++ alignas说明符是否与';新的';?,c++,c++11,new-operator,memory-alignment,C++,C++11,New Operator,Memory Alignment,我的问题很简单, alignas说明符是否与“new”一起工作?也就是说,如果一个结构被定义为对齐,那么在分配给C++17之前的new时它会对齐吗?,如果您的类型的对齐没有过度对齐,那么是的,默认的new将起作用。“过对齐”表示您在alignas中指定的对齐大于alignof(std::max\u align\u t)。默认的new或多或少会意外地与非过度对齐的类型一起工作;默认内存分配器将始终分配对齐度等于alignof(std::max\u align\u t)的内存 但是,如果您的类型对齐

我的问题很简单,


alignas说明符是否与“new”一起工作?也就是说,如果一个结构被定义为对齐,那么在分配给C++17之前的new时它会对齐吗?

,如果您的类型的对齐没有过度对齐,那么是的,默认的new将起作用。“过对齐”表示您在
alignas
中指定的对齐大于
alignof(std::max\u align\u t)
。默认的
new
或多或少会意外地与非过度对齐的类型一起工作;默认内存分配器将始终分配对齐度等于
alignof(std::max\u align\u t)
的内存

但是,如果您的类型对齐过度,则您的应用程序可能会失败。无论是默认的
new
,还是您编写的任何全局
new
运算符,都无法知道该类型所需的对齐方式,更不用说为其分配适当的内存了。帮助这种情况的唯一方法是重载类的
操作符new
,它将能够查询类与
alignof
的对齐情况

当然,如果该类被用作另一个类的成员,这将不会有用。除非另一个类也重载了
操作符new
。所以像
new pair()
这样简单的方法是行不通的

C++17中给出了所使用类型的对齐方式。这些分配器专门用于过度对齐的类型(或者更具体地说,是)。因此,
newpair()
将在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;
}
#包括
#包括
结构alignas(8)test_struct_8{char data;};
结构alignas(16)test_struct_16{char data;};
结构alignas(32)test_struct_32{char data;};
结构alignas(64)test_struct_64{char data;};
结构alignas(128)test_struct_128{char data;};
结构alignas(256)test_struct_256{char data;};
结构alignas(512)test_struct_512{char data;};
int main(){
test_struct_8*heap_8=新的test_struct_8;
test_struct_16*heap_16=新的test_struct_16;
test_struct_32*heap_32=新的test_struct_32;
test_struct_64*heap_64=新的test_struct_64;
test_struct_128*heap_128=新的test_struct_128;
test_struct_256*heap_256=新的test_struct_256;
test_struct_512*heap_512=新的test_struct_512;
#定义是对齐的(地址,大小)(((大小)(地址))%(大小))==0)
断言(与堆对齐(堆8,8));
断言(与堆对齐(堆16,16));
断言(与堆对齐(堆32,32));
断言(与堆对齐(堆64,64));
断言(与堆对齐(heap_128128));
断言(与堆对齐(heap_256,256));
断言(与堆对齐(堆512、512));
删除堆8;
删除堆16;
删除堆32;
删除堆_64;
删除堆_128;
删除堆_256;
删除堆_512;
返回0;
}

添加:可以通过
alignof(std::max\u align\u t)
查询此最大对齐。对齐度大于此值的类型称为“过度对齐”,它们的支持是有条件的、实现定义的。事实证明,我实际上不需要这些,但是知道这些很好@Nicolas:x86上的页面表需要在页面边界(0x1000)上对齐。@Nicolas将alignas与new结合使用的正确语法是什么?我尝试了下面的char*a=alignas(alignment)new char[N],但是上面写着“在'alignas'之前应该有一个主表达式”,我还没有在线找到语法示例。@sunny没有
void*运算符new(std::size\u t count)
无法直接获取用户指定的对齐方式。除非将对齐编码到计数中,但这是非常错误的。或者您可以编写一个自定义的placement new操作符,该操作符接受对齐的额外
size\t
。这是正确的,上面的答案不是。C++11将为堆栈分配的对象提供正确的对齐方式,但默认内存分配器不会提供正确的对齐方式。所以现在,您必须使用OS检测宏中包装的POSIX/windows函数。如;Linux/OSX/BSD上的posix_memalign和Windows上的aligned_alloc。对于使用英特尔MKL的用户,有MKL_malloc和MKL_free。