单例模式在工作中是最常见的设计模式;一个项目或多或少都会有那么几个类使用单例模型进行设计;
在这里就不对单例模式进行详细介绍;
在这里我将分享一个我在工作中遇到的问题:使用单例模式(饿汉)和智能指针进行类设计时,类静态指针(m_instance)初始化失败;
请看代码:
// 头文件
#include "iostream"
#include "memory"
class Sample
{
public:
static std::shared_ptr<Sample> getInstance();
int getName();
private:
Sample() = default;
Sample(const Sample&) = delete; // 禁止拷贝构造
Sample& operator=(const Sample&) = delete; // 禁止赋值操作
private:
static std::shared_ptr<Sample> m_instance;
};
// cpp文件
#include "sample.h"
//std::shared_ptr<Sample> Sample::m_instance = std::make_shared<Sample>();
std::shared_ptr<Sample> Sample::m_instance = std::shared_ptr<Sample>(new Sample());
std::shared_ptr<Sample> Sample::getInstance()
{
return m_instance;
}
int Sample::getName()
{
std::cout << "this is sample" << std::endl;
return 0;
}
可以看到,在源文件中,我写了两种m_instance的初始化方法,但是其中一条我将其注释了。
原因如下,我在某国内chatgpt上搜索 “饿汉单例模式使用智能指针”,AI给我的示例代码中,m_instance的初始赋值就是被我注释的那一条。但是结果是编译不通过,错误内容是,Sample()构造函数是私有的;
error: 'constexpr Sample::Sample()' is private within this context
使用 shared_ptr<sample>(new sample()) 则可以编译通过;
不能使用make_shared进行创建对象的原因如下:
使用 new 直接创建对象时,你可以在类的任何友元或成员函数中这样做,因为这些上下文中有权访问 private 或 protected 构造函数。
然而,std::make_shared 需要能够从调用它的上下文中访问构造函数,因为它在内部创建对象。如果构造函数是 private 或 protected,并且 std::make_shared 的调用不在允许访问这些构造函数的类或友元的上下文中,那么编译器将报错。