今天在閱讀一份第三方代碼時,看到一個內存池初始化操作如下:
1 ven::MemPool* mp = new ven::MemPool; 2 mp->init({{ 8 * 1024,{ 1000, 100 } },}); 3 mpool = mp;
在init中直接傳入了一個復雜{}包括起來的數據塊,一開始以為這是std::initializer_list的用法,那么init的參數類型就是一個std::initializer_list了。
查看init定義如下:
void init(MemPoolConf conf = MemPoolConf());也就是說{}數據塊是MemPoolConf構造函數的參數。
MemPoolConf的定義是:
typedef std::map<uint32_t, MemConf> MemPoolConf;是一個map,以一個整數為key,MemConf對象為value。
所以整個init就是對一個map進行值初始化。(C++新標准,見Primer5 page377)
MemConf定義是:
class MemConf {
public:
uint32_t init_cnt_ = 0;
uint32_t step_cnt_ = 0;
public:
MemConf(uint32_t init_cnt, uint32_t step_cnt)
: init_cnt_(init_cnt)
, step_cnt_(step_cnt)
{}
};
也就是說MemConf有兩個整數成員。這么跟蹤下來的話,對於{}數據塊的取值過程就比較明朗了。
上面提到的map容器MemPoolConf,其key是8*1024即8192。value是{1000,100},傳給MemConf的構造函數,init_cnt_cnt =1000,step_cnt_=100;
代碼實際跟蹤下來也的確如此。
當然{}數據塊的寫法,的確很容易讓人誤解。
{{ 8 * 1024,{ 1000, 100 } },}
最外面紅色大括號表示里邊放的是map的元素,第二個逗號后無內容,表示此map大小為1.那么此{}數據塊等價寫法是
{ 8 * 1024,{ 1000, 100 } } 這樣就看的清晰了。
此例說明即便碰到復雜的數據塊,碰到C++這樣的強類型語言,結合參數類型定義,一步步拆解,總會水落石出。
一開始列的代碼里第三行是個指針賦值操作。指針間的賦值是地址的賦值,此后兩個指針都指向同一個地址,也就是兩個指針所指向的內容相同。
此時要注意的是如果指針是new出來的, 那么最終的delete,只能刪除其中一個,不能兩個都delete,否則程序會崩潰。