記憶體陷阱:馴服C++中的野指標

來源:互聯網
上載者:User

 什麼是野指標?

一個母親有兩個小孩(兩個指標),一個在廚房,一個在臥室,(屬於不同的代碼塊,其生存期不同)母親讓在廚房的小孩帶一塊蛋糕(指標指向的對象)給在臥室的小孩,這樣在臥室的孩子才肯寫作業。但這個在廚房的小孩比較淘氣,他在走出廚房時自己將蛋糕吃了,沒能帶出來。而在臥室的沒有吃到蛋糕,所以不肯完成他的作業。結果母親卻不知道臥室的孩子沒有吃到蛋糕,還以為作業完了。結果第二天她就被老師召喚到辦公室了。事情麻煩了。

這樣,那個在臥室的孩子就是野指標了,因為他沒有得到應得的蛋糕,不能完成母親交給他的作業。

這就是c中所講的野指標。上面的小劇本不過示範了一種最基本的野指標的形成過程。更容易出現的情形是coder在編碼時,大意之下使用了已經free過的指標。

對於年輕點的經驗欠缺的coder來說是比較容易犯的錯誤,經驗老到的程式員或者謹慎採取成對編程的形式避免這種失誤,或者使用引用計數器防止形成野指標。

總之,在c中,野指標也許性子野,但是控制起來也是有章可循。然而事情在c++中出現了變化。

coder們面臨更大的麻煩了。c++程式員無可避免的要寫很多這樣那樣的類。誰讓c++是物件導向的呢?

我們在寫類的時候難免要用new給類的資料成員分配記憶體。這本來沒什麼,動態分配記憶體是一種很常見的基本操作,我們在學資料結構時經常這麼做,不是嗎?

但是夥計,事情並非這麼簡單。類是一種進階的使用者自訂資料類型,看起來和結構、枚舉這樣的使用者自訂類型沒啥太大差別。如果你這樣認為....?那你會死的很慘。類太複雜了,普通情況下使用類的對象並沒有太大的問題,但是,當你要複製一個對象時,問題就來了。

比如我們知道,你要用一個對象初始化另一個對象時,c++是按位進行拷貝的,即在目標對象裡建立了初始化對象的一個完全相同的拷貝。這在多數情況下已經足夠了。但是,當你的類在建立時為每個對象分配記憶體,也就是說類中有new操作。當你的對象建立好後,類也為對象分配了一塊記憶體。如果你用這個對象去初始化另一個對象時,被初始化的對象和初始化的對象完全一樣。這意味著,他們使用同一塊記憶體,而不是重新為被初始化的對象分配記憶體。

這樣麻煩就大了。如果一個對象銷毀了,那麼分配的記憶體也就銷毀了(別忘了,類是有解構函式的,它負責在對象銷毀時,釋放動態分配的記憶體。難道你說你不在類中寫上析構部分?那麼可憐的孩子,那你就走向了另一個深淵,當你的程式運行數小時之後,系統會告訴你,記憶體不夠用了。想象一下把你的程式用在騰訊的伺服器上),另一個對象就殘缺不全了,這就像一對連體嬰兒,他們共用了一部分器官,心臟或者肝臟。要救活一個,就犧牲了另一個。一個得病了,另一個也要遭殃。

可以說,這就是c++中更加變態的野指標。

什嗎?你說我不用對象初始化對象?那麼我們會不會將一個對象作為變元傳遞給函數呢?我們很多時候都這樣做。有時我們不得不將對象按值傳遞給一個函數,但是你要知道,按值傳遞是什麼意思?它的意思就是,把實參的一個拷貝傳遞給函數。這和剛才的初始化沒什麼兩樣,按位拷貝,函數體內的對象與外面的對象共用一塊記憶體,即便在函數中的對象沒有對這塊記憶體進行過操作,但是當函數結束時。。。。解構函式將會被調用......

還有一種與之相反的情況......, 當你想要把一個在函數內的對象值返回給外面的對象時,這時候,會自動產生一個臨時對象,由它容納函數的傳回值,並在函數結束時把結果傳給目標。那麼這個臨時對象迅速的被建立,並被迅速的釋放。。。一塊記憶體被釋放了兩次。其後果是不可預見的。

當你把一個對象的值賦給另一個對象時,如果你沒有重載賦值運算子,那麼也會導致按位拷貝。最終產生一個野指標(一個隱藏在類內的毒瘤),或者釋放同一塊記憶體多次。

看到了嗎?害怕了嗎?是不是感到C++到處都是陷阱呢?不但有陷阱,到處都是危險品。所有c中的疑難問題,到了c++就成了一般問題了。好了不廢話了,我們繼續講講解決之道。

對於最後的這種賦值的情況,我們只有通過重載賦值運算子才能解決,也就是避免按位拷貝。

至於前面的都屬於初始化,概括下來就是三種情況:

1.當一個對象初始化另一個對象時,例如在聲明中;

2.把所建立的對象拷貝(按值)傳遞給一個函數時;

3.產生臨時對象時,最常見的就是函數的傳回值。

解決初始化時的按位拷貝問題,我們通過建立拷貝建構函式來解決。

基本的拷貝建構函式形式為:

classname (const classname &o)

{

//body here

}

拷貝建構函式就是針對這個問題而設計的。

恩,大家都明白了吧?不要讓你的對象都變成可憐的連體人啊~~~~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.