簡體   English   中英

Singleton 和 static unique_ptr 是一個好習慣嗎

[英]Is Singleton with static unique_ptr a good practice

我在一個項目中工作,其中 Singletons 通常是這樣實現的:

class Singleton
{
public:
    static Singleton& get();
    virtual ~Singleton() = default;

    // Used for unit tests
    static void reset();

protected:
    static std::unique_ptr<Singleton>& instance();
};
unique_ptr<Singleton>& Singleton::instance()
{
    static unique_ptr<Singleton> instance;
    return instance;
}

Singleton& Singleton::get()
{
    auto& instance = instance();
    if (!instance) {
        // We cannot use make_unique<T>() as constructor is private
        instance = unique_ptr<Singleton>(new Singleton());
    }
    return *instance;
}

void Singleton::reset() { instance().reset(); }
// Private constructor
Singleton::Singleton() {}

這里不需要線程安全。
使用static unique_ptr有什么好處嗎?
使用unique_ptr<T>(new T())創建 Singleton 的后果是什么?

由於我們的單例可以攜帶(一些)全局 state,為了測試目的實現了一個 public reset() ,這是唯一的方法嗎?可以改進嗎?

我在這里找到了 C++ singleton 設計模式的一些示例。 但從來沒有像我一樣用 unique_ptr 實現過。

有兩種方法可以重置 Meyer 的 singleton:

#include <new>

class Singleton
{
public:
    static Singleton& instance() {
        static Singleton instance;
        return instance;
    }
    virtual ~Singleton() = default;

    // Option 1 - easy and convinient if Singleton is copyable or movable
    void reset1() {
        *this = {};
    }
    // Option 2 - works always
    void reset2() {
        this->~Singleton();
        new (this) Singleton;
    }

private:
    Singleton() {}
};

第二個選項基本上就是做你正在做的釋放/創建std::unique_ptr ,除了沒有釋放/分配存儲。

無需使用 std::unique_ptr。 使用參考資料

class Singleton
{
public:
    static Singleton& instance();
    virtual ~Singleton() = default;

    // Used for unit tests
    void reset();
private:
    Singleton();
    int stuff;
};

Singleton& Singleton::instance()
{
    static Singleton instance;
    return instance;
}

void Singleton::reset() { stuff = 0; }

// Private constructor
Singleton::Singleton() {}

請注意,此設計主要由您對reset function 的要求決定。這會阻止您使用某些 Singleton 實現,例如Meyer 的 Singleton

通常,您希望 singleton 實現不允許執行reset方法,因為現在您的 singleton 不再是真正的 singleton。 但出於測試目的,“淡化” singleton 當然可能是有意義的。

如果多線程安全不是問題,那么您的 singleton 實現過於復雜,可以簡化為:

class Singleton
{
public:
  static Singleton& get() {
    if (!mInstance) {
        mInstance = std::unique_ptr<Singleton>(new Singleton());
    }
    return *mInstance;
  }
  
  static void reset() { mInstance.reset(); }

private:
  static inline std::unique_ptr<Singleton> mInstance{};
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM