c++ 创建静态单例时需要MaxAlign技巧吗?

ehxuflar  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(143)

下面是来自Loki singleton implementation的代码片段,它显示了它所谓的“MaxAlign Trick”。我认为这与对齐有关(duh!),但是试图与联盟内部提到的所有类型保持一致的目的是什么呢?如果没有它,Create()内部的新布局会中断吗?

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

  }

字符串

j9per5c4

j9per5c41#

MaxAlign有两个用途。首先,它是C++11 std::max_align_t的实现:“一个普通的标准布局类型,其对齐要求至少与每个标量类型一样严格(一样大)。”(cppreference)。由于类型的对齐是具有最高对齐要求的数据成员的对齐,因此MaxAlign的定义准确地告诉我们:一个保证具有最大值的类型。针对感兴趣的平台的对齐。
其次,它也是一个足够大的缓冲区,可以包含T

char t_[sizeof(T)];

字符串
考虑到这两个方面,MaxAlign提供了C++11特性std::aligned_storage_t<size, alignment>(不考虑T的过度对齐-它可能甚至不存在)。
为什么需要:布局new要求缓冲器对于正在构造的示例适当地对准。如果没有这种“对齐技巧”,您可能会以未定义的行为结束。T是一个未知类型,Loki通过为编译代码的平台选择最大对齐来规避任何风险。
在现代代码中,您可能不会使用placement new,而是在堆栈上使用static对象,例如。

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


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

相关问题