html網(wǎng)站分頁怎么做的流量精靈app
重載new,delete?
執(zhí)行過程
重載new,delete 和普通的運算符重載不同,并非重載new,delete 的行為,而是改變內(nèi)存分配的方式,將對象放置在特定的內(nèi)存空間中
new運算符操作:
- 調(diào)用STL標準模板庫的重載operator new或operator new []函數(shù),分配足夠大的未命名內(nèi)存
- 運行相應構造函數(shù)
- 返回指向?qū)ο蟮闹羔?/li>
delete運算符操作:
- 運行相應折構函數(shù)、
- 調(diào)用STL標準模板庫的重載operator delete或operator delete[]函數(shù),釋放內(nèi)存空間
因此可以看出我們重載new,delete將改變內(nèi)存分配的方式
我們可以在全局作用域或類作用域中,自定義operator new或operator delete的版本,如果查找到自定義版本,將會使用這個版本,而非使用標準庫版本
重載new,delete
標準庫版本:
總共8個版本,其中沒有nothrow_t&的可能會拋出異常,我們可以自定義其中任一一個,對于不拋出異常的我們使用noexcept指明不拋出異常
當重載版本作為類成員時,隱式的為static,因為new在構造函數(shù)前,delete在折構函數(shù)后執(zhí)行,都不能屬于任何類對象
new接受size_t實參,且不能含有默認實參,返回類型為void*,表示把指定大小的字節(jié)數(shù)傳遞給size_t形參
對于new我們可以提供額外的形參,需要使用定位new形式
delete接受void*實參,表示這個指針指向的內(nèi)存將被釋放掉
當delete作為類成員,還可以包含另一個size_t的形參,初始值是void*指針所指對象的字節(jié)數(shù),有了size_t形參我們可以刪除繼承體系中的對象
malloc , free
我們重載了new,delete后,還要定義函數(shù)的行為,分配和釋放內(nèi)存
malloc(size_t)返回分配空間的指針
free(void*)將相關內(nèi)存返回給系統(tǒng)
定位new
定位new允許我們向new傳遞額外的參數(shù),我們可以提供一個指針,
我們知道調(diào)用new或delete運算符都會調(diào)用相應的operator版本,對于這里也一樣,會調(diào)用operator new(size_t ,? void*)版本,注意這個版本不允許用戶自定義,并且這個版本并不會分配內(nèi)存,
它會在指針(指向已經(jīng)分配了內(nèi)存的地址)實參,初始化size_t字節(jié)的對象,也就是它僅構造對象,而不會分配內(nèi)存
RTTI運行時類型識別
dynamic_cast運算符
dynamic_cast<type……>(e)
這里的type必須是類類型,
e可以為有效指針,也可以為左值或右值,同樣對應的type也是對應的類型
e可以為type的派生類或基類或同樣的類型
e將被轉(zhuǎn)換為type*類型,如果轉(zhuǎn)換失敗,結果為0,如果type是引用,拋出bad_cast異常
typeid運算符
typeid(e)e可以為任意表達式,返回對象的類型,type_info
type_info沒有默認構造,拷貝,賦值都被定義為刪除,也就是無法定義或拷貝type_info類型的對象,我們僅能通過typeid創(chuàng)建它
返回類型:
- 會忽略頂層const
- e為引用,返回引用對象的類型
- 如果是數(shù)組或函數(shù)或指針等,不會類型轉(zhuǎn)換,也就是指針返回指針類型
- e為類類型,且不包含虛函數(shù),返回e的靜態(tài)類型,否則返回e的動態(tài)類型
類成員指針
成員指針并非指向一個對象,而是指向類的成員,對于類的靜態(tài)成員,我們無需定義指向它們的指針,因為它不屬于任何對象,我們可以直接(::)訪問
對于成員指針,可以直接訪問類的非靜態(tài)成員,在沒有創(chuàng)建類對象前(雖然需要通過類對象調(diào)用),這樣做具有通用性
數(shù)據(jù)成員指針
const type classname::*p;
聲明一個數(shù)據(jù)成員指針需要指明所屬的類
p = &?classname::memberName;
初始化或賦值,也要指明所屬的類的成員,這里&將成員的地址賦給指針,要注意的是,這個過程并不指定成員所屬的類對象
classname class;? class.*p; 或?classname* class;? class->*p
當使用數(shù)據(jù)成員指針指向的數(shù)據(jù)時,需要通過成員指針訪問符.*或*p(其實就是指明了類對象,通過*解引用獲取這個類對象的p所指向的成員)
對于類成員來說,通常為private的,因此我們需要創(chuàng)建函數(shù)來訪問,這個函數(shù)返回指向classname::memberName的數(shù)據(jù)成員指針
成員函數(shù)指針
無論數(shù)據(jù)成員指針還是成員函數(shù)指針,都可以通過auto自動推斷類型,但是如果函數(shù)有重載版本,必須顯示的聲明成員函數(shù)指針
ReturnType (classname::*p)? (形參列表……)
這里p必須加括號,和函數(shù)指針一樣,否則將解釋為普通函數(shù),不能通過classname::形式直接訪問類成員
classname class;? (class.*p)(實參列表); 或?classname* class; ( class->*p)(實參列表)
注意這里p必須加括號,因為調(diào)用運算符優(yōu)先級高于成員指針訪問符,將被解釋為 class->*(p(實參列表)),p是指針,無法向函數(shù)一樣調(diào)用
成員指針別名
使用using或typedef可以讓指針更容易使用,
函數(shù)表:存儲函數(shù)指針的數(shù)組
生成可調(diào)用對象
如果想通過成員函數(shù)指針使用指向的函數(shù),必須通過成員指針訪問符.*或*p,因此成員函數(shù)和函數(shù)指針不同,它不是一個可調(diào)用對象,因此也不能作為算法的謂詞,或其他形式
std::function
function< return (形參類型列表……) > f = &classname::memberName
比如傳入迭代器時,隱式的寫法應為f(*it),這里*it作為*this的實參,顯示的寫法為(*it).*p
mem_fn
mem_fn可以讓編譯器推斷成員類型,因此不用顯示指定
bind
還可以用bind生成可調(diào)用對象