作者:baihacker
來源:http://hi.baidu.com/feixue
=============本站原創,轉載請註明出處=============
今天有朋友在QQ群上說關於new重載的問題......
於是我就寫了個程式分析一下
結論:重載new不好玩...要謹慎...何況這裡還不是全域的new(全域new能玩死人的)
有意見請到我首頁,加入黑色矩陣系列QQ群進行討論
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
class A
{
int m_x;
int m_y;
public:
A(int x, int y) : m_x(x), m_y(y) {cout << "constructor in A" << endl;}
~A() {cout << "destructor in A" << endl;}
void* operator new (size_t n, int k);
void operator delete(void* p);
void show() {cout << m_x << ',' << m_y << endl;}//鳥的VC++6.0,bug多...尤其是友元...所以不重載<<,而用個函數了
};
void* A::operator new(size_t n, int k)
{
cout << "k = " << k << endl;
cout << "new in A" << endl;
return ::new A(1, 1);
}
void A::operator delete(void* p)
{
cout << "delete in A" << endl;
if (!p)
return;
else
::delete (A*)p;
}
int main()
{
A* a = new(1) A(3, 5);
a->show();
delete a;
system("pause");
return 0;
}
VC++6.0
編譯警告:
warning C4291: 'void *__cdecl A::operator new(unsigned int,int)' : no matching operator delete found; memory will not be freed if initialization throws an exception
devc++
編譯器: Default compiler
執行 g++.exe...
g++.exe "C:/Documents and Settings/Baihacker/案頭/未命名1.cpp" -o "C:/Documents and Settings/Baihacker/案頭/未命名1.exe" -g3 -I"D:/DevSoft/DevC++/Dev-Cpp/include/c++/3.3.1" -I"D:/DevSoft/DevC++/Dev-Cpp/include/c++/3.3.1/mingw32" -I"D:/DevSoft/DevC++/Dev-Cpp/include/c++/3.3.1/backward"
-I"D:/DevSoft/DevC++/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include" -I"D:/DevSoft/DevC++/Dev-Cpp/include" -L"D:/DevSoft/DevC++/Dev-Cpp/lib" -g3
執行結束
成功編譯
運行結果:
k = 1
new in A
constructor in A
constructor in A
3,5
destructor in A
delete in A
結果分析:
1.分析到new(1)後的A,確認記憶體的結構為A的一個執行個體的結構(前面的A* a並不能說明a指向的是一個真正的A的對象,完全有可能是A的子類的對象);
2.尋找到A::operator new(size_t, int);(為什麼調用時不顯示地指出size_t呢...因為在編譯時間一定能確定這個參數,而且不可能是其它任何值,任何的改變都可能會有致命的錯誤,所以由編譯器完成,所以只需要使用者指出後面的參數了. 這樣一方面注意了效率,一方面注意了安全,而後者是主要原因);
3.屏蔽全域的new,調用 A:: operator new;
4.編譯時間確定sizeof(A);
5.調用函數A::operator new(sizeof(A), 1);
6.把指標(傳回值)賦給a;
7.調用一次a->A::A(3,5);