class A{
public:
int _a;
A(int a) :_a(a){};
};
class B{
A* _ap;
public:
B(A& a){
_ap = &a;
}
~B(){
//这里并不执行什么,但是_ap仍然被delete了。
};
};
void main(){
A* a = new A(1);
B b(*a);
delete &b;
cout << a->_a;
}
是不是不管你析构函数写的什么,都一定会delete掉其所有的成员变量?
絕對不可能。
另外,
b
不是new出來的,把它delete
掉的結果是未定義的。以上兩種可以說都是fatal error! ! !
因為前者會導致記憶體洩漏
後者會導致你的程式在某個神奇的時刻以一種神奇的方式crash掉,而且在crash掉之後你基本上很難發現其中隱含的奧秘。
題主的程式中有幾個問題:
不是。你不寫 delete 則析構函數就不會釋放對應指標指向的記憶體。
此外,題主的類別
B
在設計上也存在問題。如果一個類別的成員是一個指針,那麼需要考慮:B
的成員_ap
是指向堆疊中的物件還是動態記憶體中的物件?如果是指向堆疊中的對象,就不需要考慮記憶體的分配和釋放問題;
如果是指向動態記憶體中的對象,則需要考慮記憶體的分配和釋放問題。
如果指向動態內存,那麼指向的內存該由誰管理(分配、釋放)?是類別
B
還是類別B
的使用者(如main
函數)?如果是由類別
B
管理(這也是通常的做法),那麼對應的建構子和析構函式就會負責動態記憶體的分配和釋放。也就是 C++ 中常說的 Resource Acquisition Is Initialization(RAII)。如果由類別
B
的使用者(如main
函數)進行管理,那麼使用者(如main
函數)就必須在實現的時候仔細考慮資源的分配和釋放問題,否則很容易出錯。最後,如果不是有特殊需求,不建議使用原始指標(raw pointer),而是使用STL 裡的智慧指標
shared_ptr
、weak_ptr
和unique_ptr
,智慧指標可以自動管理所指向的動態內存,所以不需要考慮什麼時候該釋放內存、會不會多次釋放同一塊內存、會不會一不小心就搞出個野指針等問題。使用方法可以參考 C++ Primer 5e Chapter 12 Dynamic Memory。只有動態記憶體需要自己手動釋放,其餘的變數在類別變數銷毀時自動釋放。你這裡沒有動態記憶體的分配,所以什麼都不用寫
兩件事:
1、成員變數如果是指標。那麼程式需要分配的記憶體就是儲存指標所佔用的記憶體(32位元程式是4個位元組)和指標所指向的記憶體。其中指標所佔用的記憶體是有編譯器管理的,而指標指向的記憶體是你自己管理的。
也就是,這個指標所佔用的記憶體(4個位元組)就會自動在析構函式裡自動釋放。但是指標指向的部分記憶體預設析構函數是不會幫你釋放的,因為編譯器也不知道你這個指標指向的是不是你自己分配的內存,也不知道你將來還會不會用這段內存。
2、當程式/行程執行完,程式佔用的所有記憶體都會被作業系統釋放。即使沒有顯示的
delete
。