创建静态单例时需要什么 MaxAlign 技巧?
遵循 Loki 单例中的代码片段实现,它展示了所谓的“MaxAlign Trick”。我认为它与对齐有关(废话!),但是尝试与联合内提到的所有类型对齐的目的是什么?如果没有它,Create()
中的放置 new 会中断吗?
template <class T> struct CreateStatic
{
union MaxAlign
{
char t_[sizeof(T)];
short int shortInt_;
int int_;
long int longInt_;
float float_;
double double_;
long double longDouble_;
struct Test;
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
static T* Create()
{
static MaxAlign staticMemory_;
return new(&staticMemory_) T;
}
// other code...
}
Following a snippet of code from Loki singleton implementation which shows what it calls "MaxAlign Trick". I assume it has something to do with alignment (duh!), but what's the purpose of trying to align with all the types mentioned inside the union? Will the placement new inside Create()
break without it?
template <class T> struct CreateStatic
{
union MaxAlign
{
char t_[sizeof(T)];
short int shortInt_;
int int_;
long int longInt_;
float float_;
double double_;
long double longDouble_;
struct Test;
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
static T* Create()
{
static MaxAlign staticMemory_;
return new(&staticMemory_) T;
}
// other code...
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
MaxAlign
有两个目的。首先,它是 C++11 std::max_align_t 的实现:“一种简单的标准布局类型,其对齐要求至少与每个标量类型一样严格(一样大)。 ” (cppreference)。由于类型的对齐是具有最高对齐要求的数据成员的对齐,因此 MaxAlign 的定义准确地为我们提供了这一点:保证具有最大值的类型。与感兴趣的平台对齐。其次,它也是一个足够大以容纳
T
的缓冲区:从这两个方面来看,
MaxAlign
提供了 C++11 功能std::aligned_storage_t
std::aligned_storage_t
大小,对齐方式>
(不考虑T
的过度对齐 - 当时它可能甚至不存在)。但为什么需要它:放置
new
需要缓冲区针对正在构造的实例进行适当对齐。如果没有这种“对齐技巧”,您可能会得到未定义的行为。T
是一种未知的类型,Loki 通过选择代码编译平台的最大对齐方式来规避任何风险。在现代代码中,您可能不会使用新的放置,而是在堆栈上使用
static
对象,例如,但在20年前,这可能无法在跨编译器和/或多线程环境中正常工作(仅自 C++11 IIRC 起才能保证上述
T 实例
的正确初始化)。MaxAlign
serves two purposes. First, it is an implementation of the C++11std::max_align_t
: "a trivial standard-layout type whose alignment requirement is at least as strict (as large) as that of every scalar type." (cppreference). Since the alignment of a type is the alignment of the data member with the highest alignment requirements, the definition ofMaxAlign
gives us exactly that: a type that is guaranteed to have the max. alignment for the platform of interest.Second, it is also a buffer that is large enough to contain a
T
:Taking both aspects,
MaxAlign
provides the C++11 featurestd::aligned_storage_t<size, alignment>
(without taking over-alignment ofT
is into account - it probably didn't even exist back then).But why is it needed: placement
new
requires the buffer to be suitably aligned for the instance that is being constructed. Without this "alignment trick", you might end up with undefined behaviour.T
being an unkonwn type, Loki circumvents any risks by choosing the maximal alignment for the platform the code is being compiled for.In modern code, you would probably not use placement new, but use a
static
object on the stack, e.g.But 20 years ago, this might not have worked properly across compilers and/or in multi-threaded environments (proper initialisation of
T instance
in the above is only guaranteed since C++11 IIRC).