天天看點

C++ new delete執行時機和重載說明

以下代碼取自Thinking C++

#include<cstdio>
#include<cstdlib>
//using namespace std;

void* operator new(size_t sz)
{
	printf("operator new:%d Bytes\n",sz);
	void* m = malloc(sz);
	if(!m) puts("out of memory");
	return m;
}

void operator delete(void* m)
{
	puts("operator delete");
	free(m);
}

class S{
int i[100];
public:
	S(){puts("S::S()");}
	~S(){puts("S::~S()");}
};

int main(){
	puts("creating & destorying an int");
	int *p = new int[47];
	delete p;
	puts("creating & destorying an s");
	S* s = new S;
	delete s;
	puts("creating & destorying S[3]");
	S* sa = new S[3];
	delete[] sa;

	
	return 0;
}
           

其運作結果如下:

creating & destorying an int
operator new:188 Bytes
operator delete
creating & destorying an s
operator new:400 Bytes
S::S()
S::~S()
operator delete
creating & destorying S[3]
operator new:1204 Bytes
S::S()
S::S()
S::S()
S::~S()
S::~S()
S::~S()
operator delete
           

       上面的例子可以看到operator new和operator delete 重載函數并沒有顯式的調用S類的構造函數,但是列印的結果卻有構造函數和析構函數的輸出,我一直沒了解這一點。開始我人為原始的operator new是内部有調用的,但是thinking in C++ 明确說了構造函數和析構函數是編譯器決定的,是以這個想法就很有問題。但是顯然new關鍵字和operator new函數不是一個東西,換句話說他們根本不是等價的,如果你覺得重載了operator new就代表重載了new那就陷入了一個誤區。

        new關鍵字是不可以重載的,可以重載的從來隻有operator new,而operator new允許開發者重載的理由很簡單,他是用來讓你改寫存儲配置設定方案的,就是讓你配置設定指定大小記憶體塊的一個函數。

new一個對象的時候,會調用operator new,但是不等價與隻有operator new,是以編譯器回去調用你的構造函數。

從結果可以看到,new 一個對象之後,首先會配置設定記憶體(可以了解為調用operator new操作符),然後才是構造函數(這一步,由編譯器完成,換句話說,任何的重載都沒有幹預到這一步)。同樣,delete 一個對象,先調用析構(編譯器完成),然後才是operator delete操作符釋放記憶體。

以上是我在讀Thinking in C++的時候困惑的地方,當然很細心的讀者應該會覺得我說了廢話。

關于new的其它的用法參照CSDN上的一篇部落格,講的很簡單,但是包括了全部的三種情況!這裡是連結:C++ new

繼續閱讀