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

问题描述 投票:0回答: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...

  }

c++ singleton placement-new c++-loki
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>
(不考虑
T
的过度对齐 - 当时它可能甚至不存在)。

但是为什么需要它:放置

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

在现代代码中,您可能不会使用放置 new,而是在堆栈上使用

static
对象,例如

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

但是在 20 年前,这可能无法在跨编译器和/或多线程环境中正常工作(自 C++11 IIRC 起只能保证上述

T instance
的正确初始化)。

© www.soinside.com 2019 - 2024. All rights reserved.