簡(jiǎn)介:allocator類(lèi)是C++的一個(gè)模板姨蟋,它提供類(lèi)型化的內(nèi)存分配以及對(duì)象的分配和撤銷(xiāo)范嘱。
詳介:allocator類(lèi)定義在頭文件memory中吉拳。它幫助我們將內(nèi)存分配和對(duì)象構(gòu)造分離開(kāi)來(lái)暮芭。對(duì)于內(nèi)存管理想鹰,我們大都習(xí)慣使用new 和 delete胎围,畢竟這語(yǔ)句簡(jiǎn)單好記吁系。而allocator類(lèi)的用武之地體現(xiàn)在,你想更細(xì)致得去管理你的內(nèi)存白魂,減少浪費(fèi)汽纤。下面舉個(gè)例子。
#include <iostream>
using namespace std;
int main()
{
//當(dāng)我們想輸入一些單詞到一個(gè)string的數(shù)組
int n = 1000;//因?yàn)椴淮_定福荸,就給多點(diǎn)
string *p = new string[n];
string *q = p;
string word;
while (cin >> word) { //輸入
*p++ = word;
}
while (q != p) { //輸出
cout << *q++ << " " << flush;
}
cout << endl;
delete []p;
q = nullptr;
return 0;
}
new做的事情就是蕴坪,把這1000個(gè)string先默認(rèn)初始化。對(duì)于沒(méi)有默認(rèn)初始化對(duì)象的還不能用new逞姿,對(duì)需要用到的string對(duì)象辞嗡,后面進(jìn)行賦值相當(dāng)于賦值了兩次。
就比如來(lái)了10個(gè)客人滞造,主人說(shuō)要給他們倒飲料续室,但是不知道誰(shuí)要喝什么。然后你就屁顛屁顛的拿出10個(gè)杯子谒养,擺在他們面前挺狰,每個(gè)杯子底都先倒上牛奶,然后如果誰(shuí)要茶就倒掉牛奶換成茶买窟,要是果汁就倒掉牛奶換成果汁丰泊。
而allocator做的事情就是,我拿出10個(gè)杯子始绍,然后擺他們面前瞳购,什么也不干,要喝什么就給倒什么亏推,不說(shuō)話的就什么也不干学赛。
這里倒飲料的默認(rèn)構(gòu)造函數(shù)就是年堆,倒牛奶。
allocator<T> a; 定義名為a的allocator對(duì)象盏浇,可以分配內(nèi)存或構(gòu)造T類(lèi)型的對(duì)象变丧。
a.allocate(n); 分配原始的構(gòu)造內(nèi)存以保存T類(lèi)型的n個(gè)對(duì)象.
a.deallocate( p, n ) 釋放內(nèi)存,在名為p的T指針中包含的地址處保存T類(lèi)型的n個(gè)對(duì)象绢掰。
a.construct( p, t ) 在T指針p所指向的內(nèi)存中構(gòu)造一個(gè)新元素痒蓬。運(yùn)行T類(lèi)型的復(fù)制構(gòu)造函數(shù)用t初始化該對(duì)象
a.destroy(p) 運(yùn)行T*指針p所指向的對(duì)象的析構(gòu)函數(shù)
下面又要來(lái)例子了:
#include <iostream>
using namespace std;
int main()
{
int n = 1000; //老樣子給個(gè)大數(shù)
allocator<string> alloc; //擁有分配string內(nèi)存能力的alloc
auto const p = alloc.allocate(n); //分配n個(gè)未初始化的string
auto q = p;
//為string賦值
alloc.construct(q++); //*q為空
alloc.construct(q++, 10, 'c'); //*q為cccccccccc
alloc.construct(q++, "hi"); //*q為 hi
//cout << *q-- << endl; //q所指向的內(nèi)存還未構(gòu)造,會(huì)發(fā)生未知的行為
while (q != p) {
alloc.destroy(--q); //要挨個(gè)摧毀元素
}
alloc.deallocate(p, n); //摧毀內(nèi)存空間
return 0;
}
對(duì)于上面舉的牛奶的例子滴劲,我感覺(jué)還是有一點(diǎn)點(diǎn)牽強(qiáng)攻晒。我再對(duì)比一下new 和 allocator。
new做的事情是哑芹,分配內(nèi)存炎辨,然后去調(diào)用該對(duì)象的默認(rèn)構(gòu)造函數(shù)捕透。
delete 做的事情就是先摧毀對(duì)象內(nèi)容聪姿,再毀掉對(duì)象。
allocator對(duì)應(yīng)的就是分配內(nèi)存乙嘀,construct是初始化對(duì)象
destroy對(duì)應(yīng)的是摧毀對(duì)象內(nèi)容末购,deallocator對(duì)應(yīng)的就是毀掉對(duì)象。
關(guān)于要理解為什么不去默認(rèn)初始化能省內(nèi)存和摧毀要分兩步走虎谢。
我認(rèn)為先要理解這個(gè)盟榴。
當(dāng)我們?nèi)ヂ暶饕粋€(gè)數(shù)組 int arr[5],并初始化以后婴噩,我們可以發(fā)現(xiàn)擎场,arr其實(shí)是一個(gè)地址,他指向元素的首元素几莽。
(這是一個(gè)數(shù)組迅办,里面的xxxx是地址)
[[xxxx]--------------->[0000000000···01] (一串二進(jìn)制用來(lái)表示對(duì)應(yīng)的數(shù)值 )
[xxxx]--------------->[0000000000···11] (一串二進(jìn)制用來(lái)表示對(duì)應(yīng)的數(shù)值 )
[xxxx]--------------->[000000000···011] (一串二進(jìn)制用來(lái)表示對(duì)應(yīng)的數(shù)值 )
[xxxx]--------------->[0000000000···10] (一串二進(jìn)制用來(lái)表示對(duì)應(yīng)的數(shù)值 )
[xxxx]]--------------->[0000000000···01] (一串二進(jìn)制用來(lái)表示對(duì)應(yīng)的數(shù)值 )
當(dāng)我們要去初始化的時(shí)候,我們先弄出一個(gè)存放5個(gè)指針的內(nèi)存空間這個(gè)時(shí)候里面并沒(méi)有值章蚣,我們只是開(kāi)辟一個(gè)[ ]這么大的空間站欺,而里面對(duì)應(yīng)的指針?biāo)赶虻牡刂凡](méi)有構(gòu)建,只是顯示可用纤垂。就比如說(shuō)我家住在某某山上面矾策,然后把地址寫(xiě)在一張紙上(分配內(nèi)存空間),這個(gè)是我的地址峭沦,而地址指向的地方確實(shí)什么都沒(méi)有贾虽,可用。然后你說(shuō)要給我一棟別墅(賦值)吼鱼,這個(gè)時(shí)候我就去這個(gè)地址上面夯哧夯哧得去蓋別墅去蓬豁。
當(dāng)你要?dú)У暨@片空間的時(shí)候履磨,你不能只毀掉這張紙,你不能唯心的說(shuō)紙不在了別墅就不在了庆尘,你得先去把別墅毀了(destroy)剃诅,然后再把我紙燒了(deallocate)。