使用共享指针实现单例的正确方法?
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
。
你将不得不显式地new
getInstance
中的对象,这个class的成员,它可以使用私有构造函数,然后手动构造std::shared_ptr
从指向这个新对象的指针。
TLDR:您不能将 std::make_shared
用于具有私有构造函数的对象。 C++ 的规则不允许你这样做。
您可以使用私有构造函数使 std::make_unique<>()
成为 class 的友元函数。大概这也适用于 std::make_shared<>()
? (但我没有测试过。)
例如,参见:
我正在尝试我的第一个更大的 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
。
你将不得不显式地new
getInstance
中的对象,这个class的成员,它可以使用私有构造函数,然后手动构造std::shared_ptr
从指向这个新对象的指针。
TLDR:您不能将 std::make_shared
用于具有私有构造函数的对象。 C++ 的规则不允许你这样做。
您可以使用私有构造函数使 std::make_unique<>()
成为 class 的友元函数。大概这也适用于 std::make_shared<>()
? (但我没有测试过。)
例如,参见: