Singleton 单例模式

单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
一个简单的实现:

template<typename T>
T& instance()
{
    static std::unique_ptr<T> instance{new T{}};
    return *instance;
}

这里我们在函数内部定义了一个局部静态变量(local static),它只有在instance第一次被使用时才会创建实例。c++11 也规定了local static是线程安全的, 如果我们用godbolt去看一下汇编,会看到:

        movzx   eax, BYTE PTR guard variable for int& instance<int>()::instance[rip]
        ...
        mov     edi, OFFSET FLAT:guard variable for int& instance<int>()::instance
        call    __cxa_guard_acquire
        ...
        call    operator new(unsigned long)
        ...
        call    std::unique_ptr<int, std::default_delete<int> >::unique_ptr<std::default_delete<int>, void>(int*)
        mov     edi, OFFSET FLAT:guard variable for int& instance<int>()::instance
        call    __cxa_guard_release
        ...
        call    __cxa_atexit

它保证了并发的线程会等待初始化的完成。non-local static object 的初始化发生在main函数之前,所以不存在线程安全问题,但是以如果你有多个non-local static对象,他们的初始化顺序是随机的。
另外也可以写成类模板,这样其他类就可以以crtp的方式继承单例类并且拥有单例的特性:

template<typename T>
class Singleton
{
protected:
    Singleton() noexcept = default;

    Singleton(const Singleton&) = delete;

    Singleton& operator=(const Singleton&) = delete;

    // to silence base class Singleton<T> has a non-virtual destructor [-Weffc++]
    virtual ~Singleton() = default; 

public:
    static T& get_instance() noexcept(std::is_nothrow_constructible<T>::value)
    {
        // Guaranteed to be destroyed. Instantiated on first use. Thread safe in C++11
        static T instance;

        return instance;
    }
};
class TradeServer : public Singleton<TradeServer>
{
}

为什么不直接继承然后用virtual 的 get_instance(), 因为会产生vtable,增大了内存使用空间,同时增加了vtable跳转,性能下降。