日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

游戏设计模式——C++单例类

發布時間:2025/4/14 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 游戏设计模式——C++单例类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

本文將探討單例類設計模式,單例類的懶漢模式/餓漢模式,單例類的多線程安全性,最后將利用C++模板減少單例類代碼量。

本文假設有一個Manager管理類,并以此為探究單例類的設計模式。


懶漢模式

懶漢模式:顧名思義,是一種典型的拖延(lazy)策略。當第一次要用單例類的時候,再產生實例。

類聲明:

class Manager{ public: ~Manager(); //提供單例對象訪問 static Manager* getInstance(); //刪除單例對象 static void deleteInstance(); void dosomething();
protected: //構造函數聲明為 保護方法 Manager(); //單例對象指針 static Manager* s_Manager; }; //單例對象指針初始化為nullptr,防止指向了未定義的數據 Manager* Manager::s_Manager = nullptr;//提供單例類對象訪問 Manager* Manager::getInstance(){ //當沒有存在實例時(一般是指準備第一次用)時,才生成新實例 if(!s_Manager)s_Manager = new CacheManger(); return s_Manager; }//刪除單例類 void Manager::deleteInstance(){ if(s_Manager){deleted s_Manager;s_Manager = nullptr;//別忘了賦予空指針,否則指向未定義數據 } }void Manager::dosomething(){ //dosometing }

這樣我們就能在平時的程序用

Manager::getInstance()->dosomething();

來運用單例類來做某些操作了。

?

懶漢模式with線程安全

但是上面的例子,并不能保證線程安全。

假如沒有實例時,然后某兩個線程都幾乎同時使用getInstance(),那么很可能會產生2份實例,其中一份還會變成泄露的內存。

為了解決線程安全問題,自然想到用鎖:(本文使用了C++11 <mutex>的std::mutex作為互斥鎖,在類額外增加了一個靜態變量std::mutext s_mtx;)

//提供單例類對象訪問 Manager* Manager::getInstance() {if (!s_Manager) {//上鎖std::lock_guard<std::mutex> lock(s_mtx);//當沒有存在實例時(一般是指準備第一次用)時,才生成新實例if (!s_Manager){s_Manager = new Manager();}//解鎖 }return s_Manager; }//刪除單例類 void Manager::deleteInstance() {if (s_Manager) {//上鎖std::lock_guard<std::mutex> lock(s_mtx);if (s_Manager) {delete s_Manager;//別忘了賦予空指針,否則指向未定義的數據s_Manager = nullptr;}//解鎖 } }

為什么不是(上鎖,檢查,操作,解鎖)或者(檢查,上鎖,操作,解鎖),而是使用了雙重檢查(檢查,上鎖,檢查,操作,解鎖)?

  • 上鎖的成本遠遠比檢查空指針要高,且當需要產生實例時才需要鎖操作。而實際上大量多次使用getInstance時(因為已經產生了實例)并不需要上鎖,若先上鎖,則會嚴重造成性能阻塞。
  • 僅僅是檢查后再上鎖,則根本沒有做到任何線程安全。
  • ?

    餓漢模式

    餓漢模式與懶漢模式相反,是程序一開始就生成唯一實例。這樣就不用檢查是否存在實例,而且也無需考慮產生實例時的線程安全。

    class Manager { public:~Manager();//提供單例對象訪問static Manager& getInstance();void dosomething(); protected://構造函數聲明為 保護方法 Manager();//單例對象指針static Manager s_Manager; };//提供單例類對象訪問 Manager& Manager::getInstance(){return s_Manager; }

    使用方法:

    Manager::getInstance().dosomething();

    ?可以看到代碼比懶漢模式簡單多了。

    在大量使用檢查空指針造成的性能瓶頸而內存始終充足時,可以考慮使用餓漢模式

    ?

    Meyers Singleton(目前最推薦的C++單例寫法)

    class Singleton { public:static Singleton& Instance() {static Singleton theSingleton;return theSingleton;} private:Singleton();Singleton(Singleton const&);Singleton& operator=(Singleton const&); ~Singleton(); };

    這段代碼很簡單,雖然看上去和懶漢模式類似,只是static變量的位置從類移動到了實例獲取函數內。

    但是實際上由于C++的機制,當第一次調用該函數時,實例才會被構建出來。

    這樣既可以得到餓漢模式的線程安全,又可以有懶漢模式的按需分配的功能。

    ?

    應用場景注意

    ?單例類設計模式算是比較經典的一個模式,但是需要注意,它并不是想象中那么美好。

  • 它是一種換皮的全局變量。
  • 它促進了耦合。
  • 它可能對并發不友好(取決于你使用的單例寫法)。
  • 一些替代方案:

  • 當你僅需要全局可見的方法時,應該用類靜態方法而不是一個類實例。
  • 盡可能為實例提供其它便捷的訪問方式(傳參/基類獲取/服務定位器獲取等),而不是通過提供全局可見的訪問方式。
  • 如果你只是需要類保證只有唯一對象而不需要全局性,那么應對外封閉獲取實例接口(其實就是不可全局獲取實例的)。
  • 所以要注意單例類設計模式不應被泛用,通過上面的替代方案多多少少也就減少了很多不必要的單例設計。

    ?


    ?

    游戲設計模式系列-其他文章:

    https://www.cnblogs.com/KillerAery/category/1307176.html

    轉載于:https://www.cnblogs.com/KillerAery/p/9097529.html

    總結

    以上是生活随笔為你收集整理的游戏设计模式——C++单例类的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。