首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何进行c++对齐的数组分配?

如何进行c++对齐的数组分配?
EN

Stack Overflow用户
提问于 2016-03-07 04:48:07
回答 3查看 9.9K关注 0票数 8

我想修改一个数组分配:

代码语言:javascript
复制
 float * a = new float[n] ;

要使用对齐分配器,请执行以下操作。我倾向于尝试使用placement new和posix_memalign (或新的c++11等效项),但是看到了placement new with arrays is problematic with array allocations,因为compiler may need to have additional storage for count or other metadata

我试过了:

代码语言:javascript
复制
int main()
{
   float * a = new alignas(16) float[3] ;

   a[2] = 0.0 ;

   return a[2] ;
}

但是编译器似乎表明对齐被忽略了:

代码语言:javascript
复制
$ 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

看起来正确的方式是在structure declaration declare a structure with alignas中使用对齐,但这只适用于固定大小。

还有一个aligned_storage模板,但我认为它也只适用于固定大小。

有没有什么标准的方法来做一个对齐的数组分配来调用所有元素上的构造函数?

EN

回答 3

Stack Overflow用户

发布于 2016-03-07 05:03:42

正如其他人所说,不需要支持过度对齐类型。在使用之前,请检查您的编译器文档。

您可以尝试使用以下方法之一来解决问题:

1)过度分配数组(通过(desired aligment / sizeof element) - 1)并使用std::align。指向libstdc++ implementation的链接。

2)声明一个包含desired aligment / sizeof element元素数组的结构,并通过所需的对齐方式对齐。如果你使用这种结构的数组,它应该在内存中给出紧凑的表示,但你将不能使用普通的数组符号或指针算法(因为它(a)未定义的行为,(b)有很小的可能性它们不会按你想要的那样放置)

3)编写自己的对齐分配函数。请注意,您可以添加自己版本的operator newdelete

代码语言:javascript
复制
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];

您将需要分配内存,保留足够的空间来存储原始指针(由malloc返回)或指针被移位的字节数,因此后续的删除将释放corect指针,将指针对齐到所需的大小并返回它。

下面是an answerand another one,它展示了如何对齐内存。

请注意,这两个答案都使用实现定义的行为,即对转换为整数的指针进行逐位运算,然后再将其转换回来。唯一真正完全标准的方法是将内存强制转换为char*,并将其值与下一个对齐地址相加。

如果可以使用一些非标准内存分配函数,也可以将它们封装到自定义操作符new中。

票数 4
EN

Stack Overflow用户

发布于 2016-03-07 04:56:54

基本上,你被卡住是因为,在expr.new中

是否支持过度对齐类型由实现定义。

有一个proposal可以更好地支持这一点。在此之前,如果你想做你想做的事情,你将不得不使用aligned_alloc而不是new

如果你把你的数组放在一个结构中:

代码语言:javascript
复制
struct S {
    alignas(16) float _[3];
};

然后,new S将为您提供针对_的正确对齐,尽管不一定针对S本身。这可能就足够了。如果没有,那么您可以重载S本身上的operator new()operator delete(),以保证正确的行为。

票数 2
EN

Stack Overflow用户

发布于 2016-03-07 05:12:58

在C++中对对齐的本地支持仍然令人沮丧。从外观上看,您正在对齐到一个4浮点向量,所以您错过了C++14不能比16字节对齐更好的危险,但即便如此,它也不是所有C++14编译器都可靠支持的特性。如果你需要使用new float[]的可移植代码,你已经输掉了这场竞赛。

我认为,在当前的标准中,你能得到的最接近的方法是创建一个向量大小和向量对齐的数据类型(例如,使用std::aligned_storage),然后养成使用该类型,而不是单个浮点数组来进行向量数学计算的习惯。如果你需要可变长度的向量,那么你必须四舍五入到最近的4个浮点数。

(抱歉,这不是您想要的答案,但我认为这是您继续前进所需的答案。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35832358

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档