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