allocator类初学的简单例子
?
? ? ? ? 在C++中,我們基本用new(delete)操作符分配(釋放)內(nèi)存。new操作符為特定類型分配內(nèi)存,并在新分配的內(nèi)存中構(gòu)造該類型的一個對象。new表達(dá)式自動運行合適的構(gòu)造函數(shù)來初始化每個動態(tài)分配的類類型對象。即new表達(dá)式既分配了內(nèi)存同時也構(gòu)造了對象。
然而,我們一定會遇到這樣的情況:預(yù)先分配用于創(chuàng)建新對象的內(nèi)存,需要時在預(yù)先分配的內(nèi)存中構(gòu)造每個對象。即將內(nèi)存分配與對象構(gòu)造分開進(jìn)行,這樣做的理由是:
(1)在內(nèi)存分配時構(gòu)造對象很浪費,可能會創(chuàng)建從不使用的對象。
(2)當(dāng)實際使用預(yù)先分配的對象時,被使用的對象很可能要重賦新值。
string* pstr = new string[5];上面舉了個不合適的例子(當(dāng)然你應(yīng)該用vector<string>來代替),毫無疑問被分配的5個string空間是被string默認(rèn)構(gòu)造函數(shù)初始化了,而且接下來你肯定得對pstr[0...4]重新賦值。所以new操作符這種分配特點會增加運行時開銷。尤其是某些用戶的類類型要求對象分配更快一些,做法通常是:預(yù)先分配用于創(chuàng)建新對象的內(nèi)存,需要時在預(yù)先分配的內(nèi)存中構(gòu)造每個新對象。
#include <iostream> #include <string>? #include <memory> using namespace std; int main() { int n = 10; string *const p = new string[n]; string s; string *q = p;while(cin >> s && q != p + n){*q ++ = s;?? ?}?? ?const size_t len ?= q - p;cout << "There is: " << len << " elements." << endl;cout << "Hello World";delete[]p;return 0; }new有如下的特點:
(1)它將內(nèi)存分配和對象的構(gòu)造組合在了一起。相應(yīng)地,delete將對象的析構(gòu)和內(nèi)存的釋放放在了一起。
(2)如上例子,new表達(dá)式分配了并初始化了n個string,但是我們可能不需要n個string,少量的string可能就足夠了。這樣我們就可能創(chuàng)建了一些永遠(yuǎn)也用不到的對象。而且,對于那些卻是需要使用的對象,我們也在初始化之后賦予了它們新值。每個使用到的對象都被賦值了2次:第一次在默認(rèn)初始化時,第二次在賦值時。
(3)對于一個沒有默認(rèn)構(gòu)造函數(shù)的類,那么不能定義動態(tài)分配數(shù)組了。
但是,當(dāng)我們分配一大塊內(nèi)存的時候,我們一般把內(nèi)存分配和對象的構(gòu)造分離。這意味著我們可以分配大塊內(nèi)存,但是只在需要時候才真正執(zhí)行對象的構(gòu)建操作(同時付出一定的開銷)。
? ? ?allocator類將內(nèi)存分配和對象構(gòu)造分開。當(dāng)allocator對象分配內(nèi)存的時,它分配適當(dāng)大小并排列成保存給定類型對象的空間。它分配的內(nèi)存是未被構(gòu)造的,allocator的用戶必須分別construct和destroy放置在該內(nèi)存中的對象。
vector的自增長告訴我們:vector為了實現(xiàn)快速內(nèi)存分配,其實際分配的空間要比當(dāng)前需要的空間多一些。(實際空間因庫的實現(xiàn)不同而不同),下面為了說明allocator的使用,我們簡陋地實現(xiàn)STL vector中的push_back操作。
template <class T> class VECTOR { public:VECTOR() : elements(NULL), first_free(NULL), end(NULL){}void push_back(const T&); private:static allocator<T> alloc;void reallocate();T *elements;T *first_free;T *end; };elements:指向數(shù)組的第一個元素;first_free:指向最后一個實際元素之后的那個元素;end:指向數(shù)組本身之后的那個元素。看下面這張圖可能更清楚一點。
?
template <class T> void VECTOR<T>::push_back(const T& t) {if (first_free == end) //確認(rèn)是否有可用空間{reallocate(); //分配新空間并復(fù)制現(xiàn)存元素}alloc.construct(first_free, t); //構(gòu)造新元素++first_free; }?
下面是reallocate()的簡單實現(xiàn):
?
template <class T> void VECTOR<T>::reallocate() {ptrdiff_t size = first_free - elements;ptrdiff_t newCapacity = 2 * max(size, 1);T *newElement = alloc.allocate(newCapacity); //分配兩倍內(nèi)存uninitialized_copy(elements, first_free, newElement); //原內(nèi)存元素拷貝到新內(nèi)存for (T *p = first_free; p != elements; ) //原內(nèi)存元素逆序調(diào)用析構(gòu)函數(shù){alloc.destroy(--p);}if (elements){alloc.deallocate(elements, end - elements); //撤銷原內(nèi)存空間}elements = newElement; //調(diào)整新內(nèi)存空間指針指向first_free = elements + size;end = elements + newCapacity; }說明:本例只做簡單說明。如果你對vector或STL實現(xiàn)感興趣,可以拜讀《STL源碼分析》這本書,我也從這本書學(xué)到很多知識。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的allocator类初学的简单例子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++位运算符
- 下一篇: access学习网站