指標是程式設計人員的夢魘,對c語言的開發者是如此,對c++的開發者也是如此。特別是在c++中,如果不注意處理類中的指標,非常容易出問題。如果朋友們不相信可以看看下面的**:
class data
int* value;
public:
data(int num) 上面的這段問題有沒有什麼問題?大家可以自己先用筆在草稿紙上面畫一畫。然後上機用實際環境驗證一下。果不其然,系統提示記憶體發生了錯誤。為什麼呢?就是因為記憶體發生了兩次釋放。我們看以看一下process的彙編**:
21: data m(10);
0040105d push 0ah
0040105f lea ecx,[ebp-10h]
00401062 call @ilt+15(data::data) (00401014)
00401067 mov dword ptr [ebp-4],0
22: data p = m;
0040106e mov eax,dword ptr [ebp-10h]
00401071 mov dword ptr [ebp-14h],eax
23: }
00401074 lea ecx,[ebp-14h]
00401077 call @ilt+5(data::~data) (0040100a)
0040107c mov dword ptr [ebp-4],0ffffffffh
00401083 lea ecx,[ebp-10h]
00401086 call @ilt+5(data::~data) (0040100a)
0040108b mov ecx,dword ptr [ebp-0ch]
0040108e mov dword ptr fs:[0],ecx
00401095 pop edi
00401096 pop esi
00401097 pop ebx
00401098 add esp,54h
0040109b cmp ebp,esp
0040109d call __chkesp (004015b0)
004010a2 mov esp,ebp
004010a4 pop ebp
004010a5 ret
21: data m(10);
0040105d push 0ah
0040105f lea ecx,[ebp-10h]
00401062 call @ilt+15(data::data) (00401014)
00401067 mov dword ptr [ebp-4],0
22: data p = m;
0040106e mov eax,dword ptr [ebp-10h]
00401071 mov dword ptr [ebp-14h],eax
23: }
00401074 lea ecx,[ebp-14h]
00401077 call @ilt+5(data::~data) (0040100a)
0040107c mov dword ptr [ebp-4],0ffffffffh
00401083 lea ecx,[ebp-10h]
00401086 call @ilt+5(data::~data) (0040100a)
0040108b mov ecx,dword ptr [ebp-0ch]
0040108e mov dword ptr fs:[0],ecx
00401095 pop edi
00401096 pop esi
00401097 pop ebx
00401098 add esp,54h
0040109b cmp ebp,esp
0040109d call __chkesp (004015b0)
004010a2 mov esp,ebp
004010a4 pop ebp
004010a5 ret
21行:data呼叫建構函式,分配記憶體給value
22行: 這裡我們發現程式進行記憶體拷貝,那麼表示m變數value的數值和p變數中value的數值是一樣的
23行:這裡函式即將結束,所以系統呼叫m和p的析構函式,第一次析構的時候value指向的記憶體被釋放,第二次析構的時候由於p變數value的數值非0,所以也需要釋放記憶體,當然也需要進行析構處理,但是此時記憶體已經釋放了,所以記憶體進行了二次釋放,系統報錯。
經過上面的研究,我們發現了問題和原因,那麼應該怎麼解決呢?既然問題是在拷貝函式這裡,那麼就要對拷貝函式進行特殊處理。目前就我個人理解,有兩個方法供大家選擇:
(1)對拷貝建構函式進行private處理,這樣一旦出現了拷貝操作,編譯器就會提示出錯。
class data
int* value;
data(const data&) ;
public:
data(int num); (2)編寫拷貝建構函式,進行記憶體深複製
class data
int* value;
int number;
public:
data(int num)
int get_number() const
class data
int* value;
int number;
public:
data(int num)
int get_number() const
}; 我們看到,經過拷貝建構函式的定義後,原來的process函式解可以正常編譯通過,沒有問題
用彙編的眼光看C (之指標1)
指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...
用彙編的眼光看C (之指標1)
指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...
用彙編的眼光看C (之指標1)
指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...