【 聲明:版權所有,歡迎轉載,請勿用於商業用途。 聯系信箱:feixiaoxing @163.com】
有過C語言編程的朋友大多知道,如果在malloc內存之後不及時free掉內存,那麼很有可能會造成內存洩露的。那麼在C++上面,是不是也存在這樣的問題呢?結果是C++上面同樣也存在內存洩露的危險。這個危險就是如果new後面不能delete的話,也會造成內存的洩露。還有不清楚的朋友可以看看下面的示例:
class test
{
int data;
public:
test(int value):data(value) {}
~test() {};
};
void process()
{
test* t = new test(0);
if(/* some errors happens */)
{
return;
}
delete t;
return;
}
class test
{
int data;
public:
test(int value):data(value) {}
~test() {};
};
void process()
{
test* t = new test(0);
if(/* some errors happens */)
{
return;
}
delete t;
return;
} 上面的代碼在一定程度上說明了問題。其實上面這段代碼在函數返回的時候已經考慮到了內存刪除的問題,但是關鍵是如果在error發生的時候,沒有及時處理的話也會造成內存洩露的。那麼有沒有什麼好的方法呢?大家可以看看C++有沒有什麼性質可以保證函數在結束的時候可以自動完成資源的釋放。對,那就是析構函數。所以,一般的話我們可以添加一個額外的類定義。
class auto_point
{
test* t;
public:
auto_point(test* p) : t(p) {}
~auto_point() { if(t) delete t;}
};
class auto_point
{
test* t;
public:
auto_point(test* p) : t(p) {}
~auto_point() { if(t) delete t;}
}; 但是,原來我們的好多操作都是按照指針進行的,那麼怎麼把類轉變成指針呢?那就只有使用算術符重載了。
class auto_point
{
test* t;
public:
auto_point(test* p) : t(p) {}
~auto_point() { if(t) delete t;}
test* operator->() { return t;}
const test& operator* () {return *t;}
};
class auto_point
{
test* t;
public:
auto_point(test* p) : t(p) {}
~auto_point() { if(t) delete t;}
test* operator->() { return t;}
const test& operator* () {return *t;}
};
那麼有了這樣的一個定義之後,我們應該怎麼使用呢?大家可以看看下面的函數調用:
22: auto_point p(new test(0));
004010AD push 4
004010AF call operator new (00401300)
004010B4 add esp,4
004010B7 mov dword ptr [ebp-18h],eax
004010BA mov dword ptr [ebp-4],0
004010C1 cmp dword ptr [ebp-18h],0
004010C5 je process+56h (004010d6)
004010C7 push 0
004010C9 mov ecx,dword ptr [ebp-18h]
004010CC call @ILT+80(test::test) (00401055)
004010D1 mov dword ptr [ebp-1Ch],eax
004010D4 jmp process+5Dh (004010dd)
004010D6 mov dword ptr [ebp-1Ch],0
004010DD mov eax,dword ptr [ebp-1Ch]
004010E0 mov dword ptr [ebp-14h],eax
004010E3 mov dword ptr [ebp-4],0FFFFFFFFh
004010EA mov ecx,dword ptr [ebp-14h]
004010ED push ecx
004010EE lea ecx,[ebp-10h]
004010F1 call @ILT+65(auto_point::auto_point) (00401046)
004010F6 mov dword ptr [ebp-4],1
23: if(1/* some errors happens */)
004010FD mov edx,1
00401102 test edx,edx
00401104 je process+97h (00401117)
24: {
25: return;
00401106 mov dword ptr [ebp-4],0FFFFFFFFh
0040110D lea ecx,[ebp-10h]
00401110 call @ILT+75(auto_point::~auto_point) (00401050)
00401115 jmp process+0A6h (00401126)
26: }
27:
28: return;
00401117 mov dword ptr [ebp-4],0FFFFFFFFh
0040111E lea ecx,[ebp-10h]
00401121 call @ILT+75(auto_point::~auto_point) (00401050)
29: }
22: auto_point p(new test(0));
004010AD push 4
004010AF call operator new (00401300)
004010B4 add esp,4
004010B7 mov dword ptr [ebp-18h],eax
004010BA mov dword ptr [ebp-4],0
004010C1 cmp dword ptr [ebp-18h],0
004010C5 je process+56h (004010d6)
004010C7 push 0
004010C9 mov ecx,dword ptr [ebp-18h]
004010CC call @ILT+80(test::test) (00401055)
004010D1 mov dword ptr [ebp-1Ch],eax
004010D4 jmp process+5Dh (004010dd)
004010D6 mov dword ptr [ebp-1Ch],0
004010DD mov eax,dword ptr [ebp-1Ch]
004010E0 mov dword ptr [ebp-14h],eax
004010E3 mov dword ptr [ebp-4],0FFFFFFFFh
004010EA mov ecx,dword ptr [ebp-14h]
004010ED push ecx
004010EE lea ecx,[ebp-10h]
004010F1 call @ILT+65(auto_point::auto_point) (00401046)
004010F6 mov dword ptr [ebp-4],1
23: if(1/* some errors happens */)
004010FD mov edx,1
00401102 test edx,edx
00401104 je process+97h (00401117)
24: {
25: return;
00401106 mov dword ptr [ebp-4],0FFFFFFFFh
0040110D lea ecx,[ebp-10h]
00401110 call @ILT+75(auto_point::~auto_point) (00401050)
00401115 jmp process+0A6h (00401126)
26: }
27:
28: return;
00401117 mov dword ptr [ebp-4],0FFFFFFFFh
0040111E lea ecx,[ebp-10h]
00401121 call @ILT+75(auto_point::~auto_point) (00401050)
29: }
大家可以從上面的代碼看得很清楚,不管代碼在什麼時候退出,函數都會利用類的基本特性,自動調用類的析構函數,那麼進而內存就會得到釋放,不會發生內存洩露的問題。但是我們發現上面的解決方案也有不足的地方,就是每一個類都需要額外定義一個額外的定義類。那麼有沒有什麼辦法解決這一問題呢?那就是模板了。
template <typename type>
class auto_point
{
type* t;
public:
auto_point(type* p) : t(p) {}
~auto_point() { if(t) delete t;}
test* operator->() { return t;}
const test& operator* () {return *t;}
};
template <typename type>
class auto_point
{
type* t;
public:
auto_point(type* p) : t(p) {}
~auto_point() { if(t) delete t;}
test* operator->() { return t;}
const test& operator* () {return *t;}
}; 如果我們的類型不是特定的,那麼我們只需要在使用的時候按照特定的類型輸入即可
w Roman"'>)嘗試編寫一個二分法的泛型處理函數?
(3)嘗試編寫一個quick_sort的泛型函數,可能考慮的因素需要多一些?不過也可以嘗試一下哦。