创建静态单例时需要什么 MaxAlign 技巧?

发布于 2025-01-09 13:04:42 字数 863 浏览 1 评论 0原文

遵循 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风尘浪孓 2025-01-16 13:04:42

MaxAlign 有两个目的。首先,它是 C++11 std::max_align_t 的实现:“一种简单的标准布局类型,其对齐要求至少与每个标量类型一样严格(一样大)。 ” (cppreference)。由于类型的对齐是具有最高对齐要求的数据成员的对齐,因此 MaxAlign 的定义准确地为我们提供了这一点:保证具有最大值的类型。与感兴趣的平台对齐。

其次,它也是一个足够大以容纳 T 的缓冲区:

char t_[sizeof(T)];

从这两个方面来看,MaxAlign 提供了 C++11 功能 std::aligned_storage_tstd::aligned_storage_t大小,对齐方式>(不考虑T的过度对齐 - 当时它可能甚至不存在)。

但为什么需要它:放置 new 需要缓冲区针对正在构造的实例进行适当对齐。如果没有这种“对齐技巧”,您可能会得到未定义的行为。 T 是一种未知的类型,Loki 通过选择代码编译平台的最大对齐方式来规避任何风险。

在现代代码中,您可能不会使用新的放置,而是在堆栈上使用static对象,例如,

static T& Create() {
    static T instance;
    return instance;
}

但在20年前,这可能无法在跨编译器和/或多线程环境中正常工作(仅自 C++11 IIRC 起才能保证上述 T 实例 的正确初始化)。

MaxAlign serves two purposes. First, it is an implementation of the C++11 std::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 of MaxAlign 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:

char t_[sizeof(T)];

Taking both aspects, MaxAlign provides the C++11 feature std::aligned_storage_t<size, alignment> (without taking over-alignment of T 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.

static T& Create() {
    static T instance;
    return instance;
}

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文