之前開發遊戲的時候,為了能夠在任意地方都能訪問到資料,一般的做法是建立乙個資料池,然後把想要的資料全部放到資料池類中。資料池的寫法一般是建乙個名為datapool的單例類,通常情況下對單例的實現一般是這樣的
datapool.h
#pragma once
class datapool;
datapool.cpp
#include #include "datapool.h"
datapool* g_instance = null;
datapool* datapool::getinstance()
return g_instance;
}
為了方便演示資料池的工作方式,以下用遊戲中常會涉及到使用者賬戶資訊和登入資訊進行舉例。通常情況下會建立兩個類,這邊暫時定為accountinfo和logininfo。簡單實現一下,類似下面:
使用者資訊類accountinfo
accountinfo.h
#pragma once
class accountinfo
;
accountinfo.cpp
#include "accountinfo.h"
accountinfo::accountinfo(void)
accountinfo::~accountinfo(void)
登入資訊類logininfo
logininfo.h
#pragma once
class logininfo
;
logininfo.cpp
#include "logininfo.h"
logininfo::logininfo(void)
logininfo::~logininfo(void)
既然這兩個類建好了,那麼下一步就是把它們丟到datapool中,所以datapool的**也相應的更改
#pragma once
#include "accountinfo.h"
#include "logininfo.h"
class datapool;
這邊說的丟到datapool中,其實就是把這兩個類的例項作為datapool的成員變數,並且把訪問方式定位public,以後要訪問的時候一般是
datapool* pool = datapool::getinstance();
accountinfo& account = pool->m_accountinfo;
logininfo& login = pool->m_logininfo;
也就是說所有的資料都要通過datapool的單例訪問,這樣accountinfo和logininfo作為datapool的成員變數,也就擁有了單例的性質。同時也不用去管accountinfo和logininfo的記憶體釋放,因為他們的是以棧上物件的方式來宣告的,其生命週期是隨著datapool的單例來管控的。datapool什麼時候釋放,它們也跟著什麼時候釋放。
當然這樣做法問題也是非常多的,比方說如果乙個不小心把引用符號&去掉了,那麼資料就會被拷貝乙份。想象一下下面的寫法:
logininfo login = pool->m_logininfo;//這邊logininfo不是宣告為logininfo&方式的,所以logininfo的資料就被拷貝
還有乙個更讓人頭疼的問題是,由於把所有的資料都丟到datapool中,那麼相應的也得把這些資料類的標頭檔案也包含到datapool的標頭檔案中,像上面的
#pragma once
//看到了沒,需要這兩個標頭檔案
#include "accountinfo.h"
#include "logininfo.h"
class datapool;
包含標頭檔案本身沒什麼問題。問題是datapool在開發過程中會被很多人修改,一般會有3到5個人在改它。而遊戲中基本上每個業務邏輯類都要用到它,這樣就造成了乙個問題,datapool隨便一修改,相應的會有上百個檔案也一起被編譯。在沒用聯合編譯工具的情況下,最可觀的等待編譯的時間是半個小時吧。
這些都是以前用在遊戲開發的實現方案,一般是誰用誰苦逼。為此,需要對其進行改進。改進的技巧是用到了類成員模板函式以及typeid這個執行時運算子。
typeid這個運算子能夠根據型別來返回型別的名稱,舉個例子
const char* name = typeid(accountinfo).name();
printf(name);//輸出結果將是class accountinfo
name = typeid(logininfo).name();
printf(name);//輸出結果將是class logininfo
接著看看datapool改進後的樣子
#pragma once
#include #include #include #include using namespace std;
class datapool
else
return null;
}protected:
std::mapm_mapinstance;
};
它的用法是
datapool* pool = datapool::getinstance();
logininfo* info = pool->get();
logininfo* info2 = pool->get();
accountinfo* account = pool->get();
在上面例子中info和info2這兩個指標所指的物件是一樣的,因為datapool中對相同型別的資料進行了快取。這樣就可以在不改動datapool的情況下來全域性訪問自己想要的資料,只要你通過get這個類成員模板函式。
現在看看get()模板函式的實現,這個函式的用途就是根據模板引數t以及typeid來取得該模板引數的型別名稱
const char* name = typeid(t).name();//正如前面對typeid講解的那樣,這邊將根據t的型別來返回t所對應的型別名稱
然後再在map中尋找之前這個模板引數的是否有快取過,有的話直接用之前的例項。也就是這段**
std::map::iterator target = m_mapinstance.find(name);
if(target != m_mapinstance.end())
如果沒有的,那麼就建立乙個例項,然後把它加入到map中
else
通過以上改進之後,datapool就不在依賴於特定資料的標頭檔案了,同時也讓datapool固定下來,不會有大改動。自此,改進完成,有需要的各位可以試試。 小資料池和編碼問題
1.小資料池 為了快 避免重複建立 1.塊 每次執行的乙個單元 函式 類 command互動命令 eval 2.is 和 記憶體位址 id 變數名 記憶體的開闢是由直譯器決定的 is比較的是記憶體位址 判斷值是否相等 我們一直在用 在python裡面,缺省會把數字 字串 bool 進行快取,這樣不需...
python中的 小資料池 is 和
一種資料快取機制,也被稱為駐留機制 小資料池針對的是 整數 字元 布林值 其他的資料型別不存在駐留機制 在python中對 5 到256之間的整數會被駐留在記憶體中,將一定規則的字串快取.在使用的時候,記憶體中只會建立乙個該資料的物件.儲存在小資料池中.當使用的時候直接從小資料池中獲取物件的記憶體引...
遊戲開發中 Sprite 和 Image 的區別
在開發中,有的時候會遇到一些奇奇怪怪的問題,比如說在3d遊戲開發中需要製作乙個 主角血條或者 敵人血條的時候,一般來說有兩種方式,乙個是 使用 canvas 製作一張 image 進行渲染,乙個是使用 spriterenderer 進行渲染,如果使用 image進行渲染的話每乙個敵人都得引用乙個 i...