国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

內存陷阱 馴服C++中的野指針

2019-11-17 05:17:02
字體:
來源:轉載
供稿:網友

  什么是野指針?

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

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

  這就是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
}

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

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 榆社县| 伽师县| 洪江市| 无极县| 安庆市| 沈阳市| 尼玛县| 纳雍县| 江北区| 江达县| 行唐县| 青阳县| 北碚区| 黄山市| 锡林浩特市| 齐河县| 伊川县| 门头沟区| 布尔津县| 三台县| 乐安县| 城口县| 股票| 渭源县| 威信县| 类乌齐县| 清苑县| 洪泽县| 寻乌县| 靖江市| 盖州市| 鄂伦春自治旗| 治县。| 郸城县| 政和县| 浮山县| 福州市| 辰溪县| 仁寿县| 汨罗市| 乾安县|