1

遵循Loki 单例实现的一段代码,它显示了它所谓的“MaxAlign Trick”。我认为它与对齐有关(呃!),但是尝试与联合中提到的所有类型对齐的目的是什么?没有它,新的内部安置会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...

  }

4

1 回答 1

0

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

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

char t_[sizeof(T)];

考虑到这两个方面,MaxAlign提供了 C++11 特性std::aligned_storage_t<size, alignment>(不考虑 is 的过度对齐T- 它当时可能甚至不存在)。

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

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

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

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

于 2022-02-22T15:38:30.507 回答