第18章 特殊工具與技術 1

2021-12-29 20:36:28 字數 2621 閱讀 1630

18.1 優化記憶體分配

c++的記憶體分配是一種型別化操作:new為特定型別分配記憶體,並在新分配的記憶體中構造該型別的乙個物件。new表示式自動執行合適的建構函式來初始化每個動態分配的類型別。

18.1.1 c++中的記憶體分配

c++中,記憶體分配和物件構造緊密糾纏,就像析構和記憶體**一樣。使用new表示式的時候,分配記憶體,並在該記憶體中構造乙個物件;使用delete表示式時,呼叫析構函式撤銷物件,並將物件所用記憶體返還給系統。

接管記憶體分配時,必須處理兩個任務。分配原始記憶體時,必須在該記憶體中構造物件;在釋放該記憶體之前,必須保證適當地撤銷這些物件。

對未構造的記憶體中的物件進行賦值而不是初始化,其行為是未定義的。對許多類而言,這樣做引起執行時崩潰。賦值涉及刪除現存物件,如果沒有現存物件,賦值操作符中的動作就會有災難性效果。

c++提供下面兩種方法分配和釋放未構造的原始記憶體:

(1) allocater類,它提供可感知型別的記憶體分配。這個類支援乙個抽象介面,以分配記憶體並隨後使用該記憶體保護物件。

(2)標準庫中的operator new和operator delete,它們分配和釋放需要大小的原始的、未型別化的記憶體。

c++還提供不同的方法在原始記憶體中構造和撤銷物件。

(1)allocator類定義了名為construct和destroy的成員,其操作正如它們的名字所指出的那樣:construct成員在未構造記憶體中初始化物件,destroy成員在物件上執行適當的析構函式。

(2)定位new表示式(placement new expression)接受指向未構造記憶體的指標,並在該空間中初始化乙個物件或乙個陣列。

(3)可以直接呼叫物件的析構函式來撤銷物件。執行析構函式並不釋放物件所在的記憶體。

(4)演算法uninittialized_fill和uninitialized_copy像fill和copy演算法一樣執行,除了它們在目的地構造物件而不是給物件賦值之外。

現代c++程式一般應該使用allocator類來分配記憶體,它更安全靈活。但是,在構造物件的時候,用new表示式比allocator::construct成員更靈活。有幾種情況下必須用new。

18.1.2 allocator類

allocator類是乙個模板,它提供型別化的記憶體分配以及物件構造和撤銷。

allocator類將記憶體分配和物件構造分開。當allocator物件分配記憶體的時候,它分配適當大小並排列成儲存給定型別的物件的空間。但是,它分配的記憶體是未構造的,allocator的使用者必須分別construct和destroy放置在該記憶體中的物件。

1. 使用allocator管理類成員資料

vector所用儲存開始是未構造記憶體,它還沒有儲存任何物件。將元素賦值或增加到這個預分配空間的時候,必須使用allocator類的construct成員構造元素。

template 

class vector 

void push_back(const t&); 

private: 

static std::allocator alloc; 

void reallocate(); 

t* elements; //first element  

t* first_free; //behind the last actual element  

t* end; //behind vector conent  

}; template

class vector

void push_back(const t&);

private:

static std::allocator alloc;

void reallocate();

t* elements; //first element

t* first_free; //behind the last actual element

t* end; //behind vector conent

};2. 使用construct

template 

void vector::push_back(const t& t) 

template

void vector::push_back(const t& t)3. 重新分配元素與複製元素

template  

void vector::reallocate() 

if(elements) 

alloc.deallocate(elements,end-elements); 

elements=newelements; 

first_free=elements+size; 

end=elements=newcapacity; 

} template

void vector::reallocate()

if(elements)

alloc.deallocate(elements,end-elements);

elements=newelements;

first_free=elements+size;

end=elements=newcapacity;

}每次重新分配時分配兩倍記憶體。

deallocate期待指向由allocate分配的空間的指標,傳給deallocate乙個零指標是不合法的。

摘自 xufei96的專欄

第18章 特殊工具與技術 4

18.1.6 類特定的new和delete 編譯器看到類型別的new或delete表示式的時候,它檢視該類是否有operator new或operator delete成員,如果類定義 或繼承 了自己的成員new和delete函式,則使用那些函式為物件分配和釋放記憶體 否則,呼叫這些函式的標準庫版本...

第18章 特殊工具與技術 5

18.2 執行時型別識別 通過執行時型別識別 rtti 程式能夠使用基類的指標或引用來檢索這些指標或引用所指物件的實際派生型別。通過下面兩個操作符提供rtti 1 typeid操作符,返回指標或引用所指物件的實際型別。2 dynamic cast操作符,將基類型別的指標或引用安全地轉換為派生型別的指...

第18章 特殊工具與技術 6

18.2 執行時型別識別 通過執行時型別識別 rtti 程式能夠使用基類的指標或引用來檢索這些指標或引用所指物件的實際派生型別。通過下面兩個操作符提供rtti 1 typeid操作符,返回指標或引用所指物件的實際型別。2 dynamic cast操作符,將基類型別的指標或引用安全地轉換為派生型別的指...