具有子類的類,解構函式儘量定義為虛擬函式
阿新 • • 發佈:2019-01-01
由於本人才疏學淺,本文難免存在遺漏之處,歡迎大家留言指正,本人將感激不盡。
一、使用new建立物件需要顯示的呼叫Delete來刪除物件,否則將造成記憶體洩漏。
程式碼如下所示
#include <iostream> using namespace std; class Test{ public: Test(int v = 0) : data(v){ cout << "Test:" << v << endl; } ~Test(){ cout << "~Test:" << data << endl; } int data; }; int main(){ Test *p = new Test(1); Test t(2); return 0; }
輸出結果如下所示:
Test:1
Test:2
~Test:2
可以看到通過new構造的物件沒有呼叫解構函式,造成記憶體洩漏;相反,通過Test t(2)構造的物件在程式結束時呼叫了解構函式。所以,我們平時要注意用delete 刪除通過new構造的物件。
二、類具有繼承關係時,虛擬函式應該定義為虛擬函式
假設存在父類Father,子類Son,以下兩條語句均合法:
Fathe * f = new Son; //(1)
Son * s = new Son; //(2)
首先,我們要知道建立子類物件之前,會呼叫父類的建構函式,即除了子類物件之外,還會產生一個父類物件。
如果我們不將子類和父類的解構函式定義為虛擬函式時:
語句(1)將只調用父類的解構函式,而不會呼叫子類的解構函式,造成記憶體洩漏。
語句(2)正常,先呼叫子類的解構函式,接著呼叫父類的解構函式。
程式碼以及結果過如下:
#include <iostream> using namespace std; class Father{ public: Father(int v = 0) : data(v){ cout << "Father:" << v << endl; } /*virtual*/ ~Father(){ cout << "~Father:" << data << endl; } int data; }; class Son : public Father{ public: Son(int v = 0) : Father(v), data(v){ cout << "Son:" << v << endl; } /*virtual*/ ~Son(){ cout << "~Son:" << data << endl; } int data; }; int main(){ Father *f = new Son(1); delete f; Son *s = new Son(2); delete s; return 0; }
/*Father *f = new Son(1); */
Father:1
Son:1
~Father:1
/*Son *s = new Son(2);*/
Father:2
Son:2
~Son:2
~Father:2
可以看到,Father *f = new Son(2);構造的子類物件並沒有被釋放,造成記憶體洩漏。
接下來我們將子類和父類的解構函式都定義為虛擬函式,發現輸出結果如下:
Father:1
Son:1
~Son:1
~Father:1
Father:2
Son:2
~Son:2
~Father:2
此時可以看到,將父類和子類的解構函式設定為虛擬函式之後,將不再導致記憶體洩漏。
note:
1、若只將父類的解構函式定義為虛擬函式,也不會導致記憶體洩漏。
2、但是隻將子類的解構函式定義為虛擬函式,將導致core dumped,報錯如下,具體原因還未知,希望有大神讀到這篇文章時指點一下。
Father:1
Son:1
~Father:1
*** Error in `./test': free(): invalid pointer: 0x00000000017c9c28 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fca6b4b57e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fca6b4be37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fca6b4c253c]
./test[0x400b38]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fca6b45e830]
./test[0x400a19]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:01 2501473 /home/ross/Desktop/sword_offer/test/test
00601000-00602000 r--p 00001000 08:01 2501473 /home/ross/Desktop/sword_offer/test/test
00602000-00603000 rw-p 00002000 08:01 2501473 /home/ross/Desktop/sword_offer/test/test
017b8000-017ea000 rw-p 00000000 00:00 0 [heap]
7fca64000000-7fca64021000 rw-p 00000000 00:00 0
7fca64021000-7fca68000000 ---p 00000000 00:00 0
7fca6b135000-7fca6b23d000 r-xp 00000000 08:01 2626243 /lib/x86_64-linux-gnu/libm-2.23.so
7fca6b23d000-7fca6b43c000 ---p 00108000 08:01 2626243 /lib/x86_64-linux-gnu/libm-2.23.so
7fca6b43c000-7fca6b43d000 r--p 00107000 08:01 2626243 /lib/x86_64-linux-gnu/libm-2.23.so
7fca6b43d000-7fca6b43e000 rw-p 00108000 08:01 2626243 /lib/x86_64-linux-gnu/libm-2.23.so
7fca6b43e000-7fca6b5fe000 r-xp 00000000 08:01 2626173 /lib/x86_64-linux-gnu/libc-2.23.so
7fca6b5fe000-7fca6b7fe000 ---p 001c0000 08:01 2626173 /lib/x86_64-linux-gnu/libc-2.23.so
7fca6b7fe000-7fca6b802000 r--p 001c0000 08:01 2626173 /lib/x86_64-linux-gnu/libc-2.23.so
7fca6b802000-7fca6b804000 rw-p 001c4000 08:01 2626173 /lib/x86_64-linux-gnu/libc-2.23.so
7fca6b804000-7fca6b808000 rw-p 00000000 00:00 0
7fca6b808000-7fca6b81e000 r-xp 00000000 08:01 2626211 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fca6b81e000-7fca6ba1d000 ---p 00016000 08:01 2626211 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fca6ba1d000-7fca6ba1e000 rw-p 00015000 08:01 2626211 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fca6ba1e000-7fca6bb90000 r-xp 00000000 08:01 1575049 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fca6bb90000-7fca6bd90000 ---p 00172000 08:01 1575049 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fca6bd90000-7fca6bd9a000 r--p 00172000 08:01 1575049 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fca6bd9a000-7fca6bd9c000 rw-p 0017c000 08:01 1575049 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7fca6bd9c000-7fca6bda0000 rw-p 00000000 00:00 0
7fca6bda0000-7fca6bdc6000 r-xp 00000000 08:01 2626145 /lib/x86_64-linux-gnu/ld-2.23.so
7fca6bf9a000-7fca6bfa0000 rw-p 00000000 00:00 0
7fca6bfc4000-7fca6bfc5000 rw-p 00000000 00:00 0
7fca6bfc5000-7fca6bfc6000 r--p 00025000 08:01 2626145 /lib/x86_64-linux-gnu/ld-2.23.so
7fca6bfc6000-7fca6bfc7000 rw-p 00026000 08:01 2626145 /lib/x86_64-linux-gnu/ld-2.23.so
7fca6bfc7000-7fca6bfc8000 rw-p 00000000 00:00 0
7fff23521000-7fff23542000 rw-p 00000000 00:00 0 [stack]
7fff23547000-7fff2354a000 r--p 00000000 00:00 0 [vvar]
7fff2354a000-7fff2354c000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)