使用共享指针实现单例的正确方法?

Correct way to implement singleton with shared pointer?

我正在尝试我的第一个更大的 C++ 对象,但在使用共享指针实现单例时我 运行 遇到了一些问题。

当我尝试编译以下内容时,Visual Studio 给出了这个错误:

"Error C2248 'PaletteManager::PaletteManager': cannot access private member declared in class 'PaletteManager' {omitted}\xmemory line 228"

我猜这个问题是因为我有一个私有 constructor/destructor 并且 make_shared 正在尝试调用构造函数。这个访问问题对我来说很有意义,但是如果我想使用共享指针作为访问我的单例对象的方式,我该怎么办?该代码使用原始指针工作得很好,但我想尝试使用智能指针以干净的方式做事。

这里是相关代码的头文件:

class PaletteManager
{
private:

    // array representing palette colors
    uint* paletteColors;

    // private constructor/destructor because singleton
    PaletteManager();
    ~PaletteManager();

    // load palette from file TODO: not implemented
    void loadPallette();

    static std::shared_ptr<PaletteManager> instance;

public:

    const uint PALETTE_MAX_COLORS = 4;

    uint getPaletteColor(uint idx);

    // singleton accessor
    static std::shared_ptr<PaletteManager> getInstance();
};

这里是 cpp 文件中有问题的函数:

std::shared_ptr<PaletteManager> PaletteManager::instance = nullptr;

std::shared_ptr<PaletteManager> PaletteManager::getInstance()
{
    if (!PaletteManager::instance) 
    {
        PaletteManager::instance = std::make_shared<PaletteManager>();
    }

    return PaletteManager::instance;
}
PaletteManager::instance = std::make_shared<PaletteManager>();

这导致 std::make_shared 尝试 new 一个 PalletteManager 对象,然后从中构造一个 std::shared_ptr。这就是 std::make_shared 所做的,这就是它的工作原理。

这在这里行不通:那是因为 PalletteManager 有一个私有构造函数,而 C++ 库中的模板 std::make_shared 不是 friend

你将不得不显式地newgetInstance中的对象,这个class的成员,它可以使用私有构造函数,然后手动构造std::shared_ptr 从指向这个新对象的指针。

TLDR:您不能将 std::make_shared 用于具有私有构造函数的对象。 C++ 的规则不允许你这样做。

您可以使用私有构造函数使 std::make_unique<>() 成为 class 的友元函数。大概这也适用于 std::make_shared<>()? (但我没有测试过。)

例如,参见: