一個大型的C++程序中最容易出現,也是最頭疼的一個問題就是內存泄露,即忘記釋放已經申請的內存,形成程序佔用的內存不斷上升,系統性能不斷降低,甚至形成內存耗盡而致使程序崩潰。在Java中提供自動垃圾回收機制,程序在什麼時候的時機將回收內存,C++語言一直沒有將這種機制做爲語言的內部機制,可是它也提供了足夠的靈活機制,使開發人員有效地避免內存泄露。html
二、 內部封裝ios
能夠將分配和釋放的過程封裝到一個類中,即在構造的時候申請內存,析構的時候釋放內存,從而保證沒有內存泄露。下面是一個簡單的封裝類。 數組
#include
<
iostream
>
#include
<
cstring
>
using
namespace
std;
class
AutoNewDel
{ private:
char* m_szBuf;
unsigned int m_nSize;
public:
AutoNewDel(unsigned int n=1)
{ m_szBuf=newchar[n]; m_nSize=n; };
~AutoNewDel() { if(m_szBuf!=NULL) //提供安全機制
{ delete[] m_szBuf; //刪除字符數組
m_szBuf=NULL; //防止出現野指針 }
};
char* GetBuf() {
return m_szBuf; };
}
;
void
fun()
{
AutoNewDel tmpObj(100);
char* p= tmpObj.GetBuf();
strcpy(p,"one world, one dream");
cout<<p<<endl;
}
int
main()
{ fun();
cout<<"exit main"<<endl;
return0;
}
在這個例子中,封裝了char類型的內存分配和刪除,當聲明對象tmpObj時,便可得到相應的內存,並且這個內存再tmpObj對象的做用域推出時自動釋放,不須要開發人員顯示的調用delete來釋放了,避免了因爲忘記釋放內存而引發的內存泄露錯誤。 本例給出了一個最基本的思路,可是仍是存在不少問題的,好比複製構造函數和複製的問題。下面將演示這個例子的不足,修改函數fun(),增長一個賦值語句,以下:
在這個類中並無實現複製構造函數,所以編譯器自動構造一個默認的複製構造函數,執行位複製操做,即將對象tmpObj的內容逐字地複製到對象tmpObj2中,兩個對象中的m_szBuf指向同一塊內存,當對象銷燬時,
m_szBuf會被銷燬兩次,從而形成程序錯誤(本博客還有一篇隨筆說明相關的內容,隨筆地址爲:C++ primer plus第十一章 使用類的程序)。簡單的解決辦法就是禁止複製構造函數,在類中聲明覆制構造函數爲私有。可是這樣治標不治本,它限制類的功能實現。能夠經過一個引用一個計數的方法,即避免了對同一塊內存的屢次刪除,也容許複製構造函數。 引用的計數的原理是這樣的,就是對要使用的內存維護一個計數器,記錄當前有多少指針指向這塊內存。當有指針指向這塊內存時,計數器加1;反之,當指向這塊內存指針銷燬時,計數器減1。當這塊內存的計數器爲0時,才容許刪除這塊內存。能夠在類的構造函數和析構函數中分別完成加1和減1的操做。代碼以下:
#include
<
iostream
>
#include
<
cstring
>
using
namespace
std;
class
AutoNewDel
{ // Attribute
private:
char* m_szBuf;
unsigned int m_nSize;
int* m_count; //新增長的語句
public:
AutoNewDel(unsigned int n=1)//在構造函數中申請內存
{
m_szBuf=newchar[n];
m_nSize=n;
//新增長的語句
m_count=newint;
*m_count=1;
cout<<"count is : "<<*m_count<<endl;
};
//新增長的複製構造函數
AutoNewDel(const AutoNewDel & s)
{ m_nSize=s.m_nSize;
m_szBuf=s.m_szBuf;
m_count=s.m_count;
(*m_count)++;
cout<<"count is : "<<*m_count<<endl;
}
~AutoNewDel()
{
(*m_count)--;
cout<<"count is : "<<*m_count<<endl;//新增長的兩條語句
if(*m_count==0)
{
cout<<"buf is deleted"<<endl;
if(m_szBuf!=NULL) //提供安全機制
{ delete[] m_szBuf; //刪除字符數組
m_szBuf=NULL; //防止出現野指針
if(m_count!=NULL)
{
delete m_count;
m_count=NULL;
}
}
}
};
char* GetBuf() {
return m_szBuf; };
}
;
void
fun()
{
AutoNewDel tmpObj(100);
char* p= tmpObj.GetBuf();
strcpy(p,"one world, one dream");
cout<<p<<endl;
AutoNewDel tmpObj2=tmpObj;
cout<<"tmpObj2.m_szBuf = "<<tmpObj2.GetBuf()<<endl;
}
int
main()
{
fun();
cout<<"exit main"<<endl;
return0;
}
程序輸出結果以下: