是否有便携式方式来确定任何类型的最大可能对齐方式是什么?
例如在x86上,SSE指令需要16字节对齐,但据我所知,没有指令需要更多,因此任何类型都可以安全地存储到16字节对齐的缓冲区中。
我需要创建一个缓冲区(例如char数组),我可以在其中编写任意类型的对象,因此我需要能够依赖缓冲区的开头进行对齐。
如果所有其他方法都失败了,我知道分配带new
的char数组可以保证最大对齐,但使用TR1 / C ++ 0x模板alignment_of
和aligned_storage
,我想知道是否可以在我的缓冲区类中就地创建缓冲区,而不是要求动态分配的数组的额外指针间接。
想法?
我意识到有很多选项可以确定一组有界类型的最大对齐:一个联合,或者只是来自TR1的alignment_of
,但我的问题是这些类型是无界的。我事先并不知道哪些对象必须存储在缓冲区中。
答案 0 :(得分:12)
在C ++ 11中,标题cstddef中定义的std :: max_align_t是一种POD类型,其对齐要求至少与每个标量类型的对齐要求一样严格(大)。
使用新的alignof运算符,就像alignof(std::max_align_t)
答案 1 :(得分:10)
在C ++ 0x中,Align
std::aligned_storage<Len, Align>
模板参数的默认参数为“default-alignment”,定义为(N3225§20.7.6.6表56):
对于任何大小不超过
Len
的C ++对象类型,default-alignment的值应该是最严格的对齐要求。
目前尚不清楚SSE类型是否会被视为“C ++对象类型”。
默认参数不是TR1 aligned_storage
的一部分;它是为C ++ 0x添加的。
答案 2 :(得分:5)
缺少一些所有编译器都忠实地支持所有架构的maximally_aligned_t
类型,我不知道如何在编译时解决这个问题。如你所说,潜在类型的集合是无限的。额外的指针间接是真的那么重要吗?
答案 3 :(得分:5)
不幸的是,确保最大对齐比应该更加困难,并且没有保证解决方案AFAIK。来自GotW博客(Fast Pimpl article):
union max_align {
short dummy0;
long dummy1;
double dummy2;
long double dummy3;
void* dummy4;
/*...and pointers to functions, pointers to
member functions, pointers to member data,
pointers to classes, eye of newt, ...*/
};
union {
max_align m;
char x_[sizeofx];
};
这不能保证完全 便携式,但在实践中它很接近 因为很少或没有 系统不适用于此 预期
这就是我所知道的最接近的'黑客'。
我个人使用另一种方法进行超快速分配。请注意,这是邪恶的,但我在光线追踪领域工作,速度是最好的质量衡量标准之一,我们每天都会编码。它涉及使用具有预分配内存的堆分配器,其工作方式类似于本地堆栈(仅在分配时递增指针并在解除分配时递减1)。
我特别将它用于Pimpls。但是,仅仅拥有分配器是不够的;为了使这样的分配器工作,我们必须假设一个类Foo的内存在构造函数中分配,同样的内存同样只在析构函数中释放,并且Foo本身是在堆栈上创建的。为了安全起见,我需要一个函数来查看类的'this'指针是否在本地堆栈上,以确定我们是否可以使用我们的超快速堆栈堆栈分配器。为此我们必须研究特定于操作系统的解决方案:我使用TIBs和TEBs用于Win32 / Win64,我的同事找到了Linux和Mac OS X的解决方案。
结果,在研究了特定于OS的方法来检测堆栈范围,对齐要求以及进行大量测试和分析之后,结果是一个分配器,它可以根据我们的滴答计数器基准在4个时钟周期内分配内存。反对malloc / operator new约400个周期(我们的测试涉及线程争用,因此在单线程情况下malloc可能比这个快一点,可能是几百个周期)。我们添加了一个每线程堆栈并检测到正在使用哪个线程,这将时间增加到大约12个周期,尽管客户端可以跟踪线程分配器以获得4个周期的分配。它消除了地图上基于内存分配的热点。
虽然您不必经历所有麻烦,但编写快速分配器可能更容易且更普遍适用(例如:允许在运行时确定分配/解除分配的内存量),而不是{{ 1}}这里。 max_align
很容易使用,但是如果你的内存分配速度很快(假设你已经分析了你的代码并在malloc / free / operator new / delete中找到热点,主要贡献者在你的代码中)有控制权,编写自己的分配器可以真正发挥作用。
答案 4 :(得分:1)
分配对齐的内存比看起来更复杂 - 例如参见 Implementation of aligned memory allocation
答案 5 :(得分:-2)
这就是我正在使用的。除此之外,如果你正在分配内存,那么长度大于或等于max_alignment的新的()数组char将与max_alignment对齐,这样你就可以使用索引到该数组中来获得对齐的地址。
enum {
max_alignment = boost::mpl::deref<
boost::mpl::max_element<
boost::mpl::vector<
boost::mpl::int_<boost::alignment_of<signed char>::value>::type,
boost::mpl::int_<boost::alignment_of<short int>::value>::type,
boost::mpl::int_<boost::alignment_of<int>::value>::type, boost::mpl::int_<boost::alignment_of<long int>::value>::type,
boost::mpl::int_<boost::alignment_of<float>::value>::type,
boost::mpl::int_<boost::alignment_of<double>::value>::type,
boost::mpl::int_<boost::alignment_of<long double>::value>::type,
boost::mpl::int_<boost::alignment_of<void*>::value>::type
>::type
>::type
>::type::value
};
}