Pee*_*oot 8 c++ arrays alignment
我想修改一个数组分配:
float * a = new float[n] ;
Run Code Online (Sandbox Code Playgroud)
使用对齐的分配器。我倾向于尝试使用placement new 和posix_memalign(或新的c++11 等价物),但看到placement new with arrays 在数组分配方面存在问题,因为编译器可能需要为计数或其他元数据提供额外的存储空间。
我试过:
int main()
{
float * a = new alignas(16) float[3] ;
a[2] = 0.0 ;
return a[2] ;
}
Run Code Online (Sandbox Code Playgroud)
但编译器似乎表明 alignas 被忽略:
$ g++ -std=c++11 t.cc -Werror
t.cc: In function ‘int main()’:
t.cc:4:39: error: attribute ignored [-Werror=attributes]
float * a = new alignas(16) float[3] ;
^
t.cc:4:39: note: an attribute that appertains to a type-specifier is ignored
Run Code Online (Sandbox Code Playgroud)
看起来使用 alignas 的正确方法是 结构声明中声明一个结构,但这仅适用于固定大小。
还有一个aligned_storage 模板,但我认为它也只适用于固定大小。
是否有任何标准方法可以进行对齐的数组分配,以在所有元素上调用构造函数?
正如其他人所说,不需要支持过度对齐的类型。使用前请检查编译器文档。
您可以尝试使用以下方法之一来解决您的问题:
1)过度分配数组(通过(desired aligment / sizeof element) - 1)并使用std::align。libstdc++实施链接。
2) 声明一个包含元素数组desired aligment / sizeof element并按所需对齐方式对齐的结构。如果您使用此类结构的数组,它应该在内存中为您提供紧凑的表示,但您将无法使用正常的数组表示法或指针算术(因为它(a)未定义的行为,(b)它们有很小的机会不是按照你想要的方式放置)
3) 编写自己的对齐分配函数。请注意,您可以添加自己版本的运算符new和delete。
namespace my
{
struct aligned_allocator_tag {};
aligned_allocator_tag aligned;
}
void* operator new( std::size_t count, my::aligned_allocator_tag, std::size_t aligment);
void* operator new[]( std::size_t count, my::aligned_allocator_tag, std::size_t aligment)
{
return ::operator new(count, my::aligned, aligment);
}
//Usage
foo* c = new(my::aligned, 16) foo[20];
Run Code Online (Sandbox Code Playgroud)
您将需要分配内存,保留足够的空间来存储原始指针(由 malloc/其他返回)或指针被移位的字节量,因此后续删除将释放正确的指针,将指针对齐到所需的大小并返回它。
请注意,这两个答案都使用实现定义的行为,即对转换为整数的指针进行按位算术并将其转换回来。唯一真正完全标准的方法是将内存转换为char*并添加其值与下一个对齐地址之间的差异。
如果您可以使用一些非标准内存分配函数,您new也可以将它们包装到自定义运算符中。
基本上,你被困住了,因为在 [expr.new] 中:
是否支持过度对齐类型是由实现定义的。
有一项提案可以更好地支持这一点。在那之前,如果您想做您想做的事情,aligned_alloc 则必须使用new.
如果将数组粘贴在结构中:
struct S {
alignas(16) float _[3];
};
Run Code Online (Sandbox Code Playgroud)
thennew S将为您提供正确的对齐方式_,但不一定适合S其本身。这可能就足够了。如果没有,那么您可以重载operator new()andoperator delete()本身S以保证正确的行为。
| 归档时间: |
|
| 查看次数: |
9412 次 |
| 最近记录: |