????????單例模式實際上就是為了確保一個類最多只有一個實例,并且在程序的任何地方都可以訪問這個實例,也就是提供一個全局訪問點,單例對象不需要手動釋放,交給系統來釋放就可以了,單例模式的設計初衷就是為了在整個應用程序的生命周期中只創建一個實例,并且在需要時重復使用該實例,而不是頻繁地創建和銷毀對象。因此,在應用程序運行期間,單例對象通常會一直存在,直到應用程序結束。
? ? ? ? 一般來說,實現單例模式的方式有兩種,一種是懶加載的方式,另外一種是預加載的方式。
實際上實現單例模式的基本步驟其實是一樣的。第一步都是將構造函數和析構函數私有化,然后定義一個靜態單例對象和聲明一個靜態單例對象獲取函數,最后初始化單例對象和定義單例對象獲取函數。
????????懶加載:當使用到單例對象的時候,才創建這個對象。
main函數
#include"Test.h"
#include<iostream>
int main()
{Test*t1=Test::get_instance();Test*t2=Test::get_instance();std::cout<<"t1:"<<t1<<std::endl;std::cout<<"t2:"<<t2<<std::endl;return 0;
}
Test.h?
????????將構造函數私有化,可以阻止外部代碼直接實例化類的對象,強制使用單例模式提供的靜態方法來獲取類的唯一實例。這樣可以確保在整個應用程序中只有一個實例存在。通過私有化析構函數,可以防止外部代碼直接刪除單例對象,從而確保單例對象在整個應用程序的生命周期內保持存在。這有助于避免意外的對象銷毀和內存泄漏。
????????將單例對象(t_instance)聲明為靜態的是為了確保單例對象的唯一性、全局訪問性和簡化訪問方式。靜態單例對象可以在整個應用程序中被直接訪問,避免多次實例化的情況發生,符合單例模式的設計原則
class Test
{
public:
static Test*get_instance();
private:
Test();
~Test();
static Test*t_instance;
};
?Test.cpp
#include"Test.h"
Test*Test::t_instance=nullptr;
Test *Test::get_instance()
{if(t_instance==nullptr){t_instance=new Test();}return t_instance;
}
Test::Test()
{}
Test::~Test()
{
delete t_instance;
}
運行代碼,可以發現,兩個Test對象的地址是一樣的,也就是說明這兩個對象是同一個對象。?
上面這種寫法的懶加載其實是線程不安全的,當多個線程調用get_instance函數時,可能會創建出多個對象,將單例獲取函數改進一下就可以了。
#include<mingw.mutex.h>
class Test
{
public:
static Test*get_instance();
private:
Test();
~Test();
static Test*t_instance;
static std::mutex tmutex;
};
#include"Test.h"
Test*Test::t_instance=nullptr;
std::mutex Test::tmutex;
Test *Test::get_instance()
{if(t_instance==nullptr){std::lock_guard<std::mutex>lk(tmutex);t_instance=new Test();}return t_instance;
}
Test::Test()
{}
Test::~Test()
{
delete t_instance;
}
? ? ? ? 預加載:程序啟動的時候,就將對象創建好。
只需要更改懶加載的Test.cpp就可以了,不必判斷單例對象是否為空,在類被第一次使用的時候就直接創建好了單例對象。
#include"Test.h"
Test*Test::t_instance=new Test();
Test *Test::get_instance()
{return t_instance;
}
Test::Test()
{}
Test::~Test()
{
delete t_instance;
}