在C++中也是少不了對內存的管理,在C++中只要有new的地方,在寫代碼的時候都要想着delete。 new分配的時堆內存,在函數結束的時候不會自動釋放,若是不delete我分配的堆內存,則會形成內存泄露。因此咱們要學會內存管理,不要內存泄露。在C++中的內存管理機制和OC中的還不太同樣,在OC中的ARC機制會給程序員的內存管理省很多事,但在C++中沒有ARC因此咱們要本身管理好本身開闢的內存。Java中也有本身相應的內存管理機制,好比JDBC裏的獲取的各類資源在finally裏進行close等程序員
那麼什麼狀況下咱們寫的程序會出現內存泄露呢?下面咱們將會舉一個簡單的例子來分析一下C++中的內存管理機制。函數
1.創建一個測試類TestClass, TestClass類中有一個私有的屬性(指針類型),有一個無慘的構造函數,有一個析構函數,還有一個display方法用於輸出對象的信息測試
測試類的聲明以下:this
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//內存管理的測試類
class
TestClass
{
private
:
char
*name;
public
:
//無參構造函數
TestClass();
//析構函數
~TestClass();
//描述方法
void
display();
};
|
在xxx.cpp文件中定義類的實現方法spa
實現構造方法,實現構造方法時要給屬性指針分配空間,否則的話屬性指針沒有分配內存地址,調用時程序會崩潰,用new方法進行堆分配指針
1
2
3
4
5
6
7
8
9
|
//無參構造函數
TestClass::TestClass()
{
cout <<
"TestClass()"
<<endl;
//給指針屬性分配內存(堆分配)
this
->name =
new
char
[255];
//進行初始化
strcpy
(
this
->name,
"ludashi"
);
}
|
實現析構函數在析構函數中要對構造函數中堆分配的內存進行delete,否則會形成內存泄露code
1
2
3
4
5
6
|
//析構函數
TestClass::~TestClass()
{
delete
[]
this
->name;
cout <<
"~TestClass()"
<< endl;
}
|
實現display函數,進行name的打印測試對象
1
2
3
4
5
|
//描述方法
void
TestClass::display()
{
cout <<
this
->name <<endl;
}
|
2. 在main函數中進行測試內存
實例化對象時進行堆分配:須要手動進行內存的釋放,否則也會形成內存的泄露ci
1
2
|
//TestClass類的初始化,堆分配,須要delete
TestClass * testClass =
new
TestClass();
|
實例化對象的棧分配:不須要手動釋放內存,大括號結束時就自動釋放棧內存
1
2
|
//棧分配,不用delete,出大括號後自動釋放
TestClass stackClass = TestClass()
|
信息的打印輸出
1
|
testClass->display();
|
調用delete來釋放堆分配的對象
1
|
delete
testClass;
|
3.程序運行結果:若是不加delete testClass; 析構函數只會調用一個,由於堆分配的對象不會自動釋放,須要手動釋放,不加則會形成內存的泄露
1
2
3
4
5
|
TestClass()
TestClass()
ludashi
~TestClass()
~TestClass()
|
4.拷貝構造函數
若是在main函數中加入下面這句話,程序在運行時就會崩掉,若是要想程序正常運行能夠把析構函數中的delete [] this->name;註釋掉就能夠運行。不過這樣會引發內存的泄露。那麼咱們來研究一下爲何加上下面這句話程序會崩掉呢?緣由是下那句話的意思是copyTest和stackClass指向同一塊棧內存,當其中一個調用析構函數時就會把name給delete掉,另外一個在析構調用delete時就會報錯。怎麼從基本上解決問題呢?接下來就是拷貝構造函數出場的時候啦。
1
|
TestClass copyTest = stackClass;
|
下面是拷貝構造函數的定義方法
1
2
3
4
5
6
7
8
|
//拷貝構造函數
TestClass::TestClass(
const
TestClass &test)
{
//在堆中分配新的內存
this
->name =
new
char
[255];
//進行拷貝
strcpy
(
this
->name, test.name);
}
|
在main函數中調用拷貝構造函數 ,這樣的代碼有不會有剛纔的問題了
1
|
TestClass copyTest = stackClass;
|
5.再提內存管理,不由又想到初學C++那會的一句話「先構造的後析構」;有new的地方就得想着delete,爲了不內存泄露。
上面的拷貝構造函數的做用是在聲明對象的時候能夠利用拷貝構造函數給新的對象賦值,若是像下面的這種狀況就會出現過分釋放的問題;
1
2
3
|
TestClass test1 = TestClass();
TestClass test2 = TestClass();
test2 = test1;
|
接下來就該操做符重載出場的時候了(operator = )把=號進行重載
1
2
3
4
5
6
|
//對象之間的賦值:操做符重載
TestClass & TestClass :: operator = (
const
TestClass &test)
{
strcpy
(
this
->name, test.name);
return
*
this
;
}
|