1. placement new 方法
如:pi = new (ptr) int; //placement new
括號裏的參數是一個指針,它指向一個內存緩衝器,new操作將在這個緩衝器上分配一個對象。Placement new的返回值是這個被構造對象的地址(比如扣號中的傳遞參數)。placement new主要適用於:在對時間要求非常高的應用程序中,因爲這些程序分配的時間是確定的;
STL 標準庫中 allocator 空間分配器, 就使用了這個語法。
先使用 malloc 分配內存p. 然後 在該內存內構造自己的類對象 new(p) T1(value) ; T1 是構造的類型,value 是類型的值
2. naked function
當你的函數內部較簡單,用不到太多寄存器。或者需要根據上下文決定一些寄存器變量的時候。可以用naked 函數。對於一般的函數,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。naked call不產生這樣的代碼。使用naked函數,我們可以自己編寫乾乾淨淨的函數,特別是當你代碼沒有使用這些寄存器的時候。可以像內聯函數一樣,省略一些操作。
void __declspec(naked) MyNakedFunction()
{
// Naked functions must provide their own prolog.
__asm
{
PUSH EBP
MOV ESP, EBP
SUB ESP, __LOCAL_SIZE
}
// And we must provide epilog.
__asm
{
POP EBP
RET
}
}
3. 指向類成員函數的指針
在MFC庫中很多窗口基類中調用派生類的消息處理函數。因爲windows消息衆多,如果爲每個消息都設立虛函數,而每個虛函數都佔用4 bytes,那樣很多類體積將非常龐大。而且有些地方基類設計時考慮到派生類在此可能要作些處理,又不想使用虛函數的話也可以使用指向成員函數的指針。如下面的類。如果派生類沒有修改pf成員,在release中 (this->*pf)() 將被優化掉。而且使用指向成員函數的指針也不用定死函數名字.
class animate
{
typedef void (animate::*pfun)();
public:
animate() {pf=static_cast<pfun>(donothing);}
void sleep()
{
cout<<"animate sleep"<<endl;
(this->*pf)();
}
void donothing(){}
pfun pf;
};
class fish:public animate
{
public:
fish() {pf = static_cast<pfun> (test);}
void test()
{
cout<<"使用基類指針調用派生類非虛函數"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
animate* fs = new fish;
fs->sleep();
delete fs;
return 0;
}
4 __declspec(novtable)
C++中沒有提供類似interface這樣的關鍵字來定義接口,但是Mircrosoft c++中提供了__declspec(novtable)來修飾一個類,來表示該類沒有虛函數表,也就是虛函數都(應該)是純虛的
聲明的基類沒有 vtable(虛擬函數表), 但還是有vptr指針(指向虛擬函數表)的。所以a1* a= new a1; a->hello()執行將會出錯 。 而從a1派生的b1是有vtable的。所以 a1* a = new b1; a->hello() 將調用 b1 的hello函數。如果b1未定義hello函數,那麼將調用 a1 函數。其實還是從b1對象的vptr指向的vtable中索引的函數地址。編譯時由於b1中沒有定義hello虛函數. vtable 中虛函數hello指向的是a1類hello函數地址。良好的面向對象設計應該由派生類完成實現。面向對象規則第一條就是基於接口編程。所以將a1 函數均定義爲純虛函數,a1相當於接口,由派生類b1來實現,這樣將抽象與實現之間解耦合,更符合面向對象規範。
這樣定義的類a1不能調用虛函數。所以a1 類應看成接口。不應生成 a1 類對象。同樣程序生成時將節省a1 類 vtable 的空間。如果有大量虛函數,節省空間還是可觀的 函數個數*4.
次關鍵字爲vc 所有,其他c++編譯器並不支持
class __declspec(novtable) a1
{
public:
a1() {}
virtual void hello()
{
cout<<"a hello"<<endl;
}
};
class b1:public a1
{
public :
b1() {}
void hello()
{
cout<<"b hello"<<endl;
}
};