如何讓C 函式返回值死心塌地為你工作

2022-09-26 10:03:47 字數 2463 閱讀 1553

本文主要研究的是c++函式返回值,你必須注意的問題,下面進入正題。

c++太繁雜了,先接觸c++後接觸python這樣的語言,你就再也不想碰它,因為,就連乙個函式返回值都一大堆的說道,這裡面的玄機,連工作三年的c++熟手都未必能準確的理解和運用。

歸根結底,c++所面臨的問題要求它提供各種各樣的機制以保證效能,也許,這輩子也見不到c++能安全有效的自己進行記憶體垃圾**。。。。。

老程式猿都會提醒菜鳥,注意函式的返回值,因為,很可能,你的函式返回的資料在後續的使用中會出錯。那麼函式在返回值時要注意什麼呢?

本篇部落格嘗試用最簡練的普通大白話,講解函式返回值的問題。

c++把記憶體交給了程式猿,但是,請你注意,它可沒把所有的記憶體都交給你,交給你的只是堆上的記憶體,程式設計客棧也就是你通過malloc函式 和new 關鍵字申請來的記憶體,除了這些記憶體以外,其他的記憶體,你最好別碰,最好別碰,最好別碰,重要的事情說三遍。

如果你的函式返回值在後續使用**錯了,尤其是返回函式內的區域性變數這種事情,那麼,基本可以肯定,你碰了不該碰的記憶體。這時候,你會覺得自己很冤枉啊,我沒有啊。但事實是,沒有冤枉你,所以,為了不被bug檢察院起訴你,作為乙個c++程式猿,你必須學會甄別那些記憶體程式設計客棧是能碰的,那些記憶體是不能碰的。

char *pstr = "this is the buffer text";

return pstr;

如果你的函式是這麼寫的,那麼恭喜你,返回正確,因為這個pstr指向的是常量儲存區,這裡的記憶體,你是可以碰的,但是注意,這個碰,僅僅是讀,你想修改,那是萬萬不可以的。

char buffer = "this is the buffer text";

return buffer;

如果你的函式是這麼寫的,那麼恭喜你,等著bug聯邦檢察院起訴你吧。這裡的buffer指向的是棧上記憶體,這個,就是你碰不得的,前面的pstr就好比公園,公園嘛,大家都可以來玩,但是你不能把公園裡的假山拆了,你也不能把公園裡的樹砍了,你只能是來玩,不能修改它,棧上的記憶體,就好比是私家花園,你乙個外人,是不能進去的。那麼怎麼甄別的,方法倒也簡單,你見到帶中括號的,就應該明白,這東西是棧上的,出了這個函式,你就別想再碰的,你只要敢碰,bug聯邦檢察院就會起訴你。

static char buffer = "this 程式設計客棧is the buffer text";

return buffer;

如果你的函式是這麼寫的,那麼恭喜你,返回正確,可是剛才不是明明說,這裡是私家花園嘛,沒錯,但是你注意看,前面還加了乙個static,只要加了這個關鍵字,就相當於說國家把這個私家花園徵用了,那麼,它就從私家花園變成了靜態儲存區里的乙個小花園,靜態儲存區里的記憶體,國家說,靜態儲存區對外開放,你們都可以來。

函式返回的都是值拷貝,棧上的記憶體,在函式結束的時候,都會被收回。在函式內部,你可以碰棧上的記憶體,那是因為這個時候你是在棧的家裡做客,那他們家的記憶體小花園當然允許你訪問,可是函式結束了,就相當於你離開了棧的家,棧把記憶體小花園的門關上了,你怎麼可以進去,你進去了,就會被bug聯邦法院起訴!

但是呢,總有一些奇怪的現象讓你以為你可以在函式結束後仍然可以訪問棧上的記憶體。

我們定義乙個結構體

struct person

寫乙個函式

person* getperson2()

在得到函式的返回值以後,你可以輸出物件的年齡

person *p2 = getperson2();

cout

你會發現,這段**居然可以正確執行!在函式getperson2內部,p這個變數是區域性變數,必然是在棧上申請的,返回的是&p,這不就是棧上的記憶體位址麼,那為啥在函式外部,卻仍然可以輸出age呢?

雖然,函式結束後,物件被銷毀,但是銷毀的不夠徹底,似乎計算機在管理記憶體時也不需要那麼徹底的銷毀乙個物件,你之所以能輸出age,那是因為那個區域,沒有被徹底銷毀,這一小塊的記憶體(儲存age的4個byte)沒有發生變化。你可以暫時的碰這塊記憶體,但遲早是要出問題的,如果某一刻,計算機打算用這塊記憶體,發現你在非法使用,那麼必然會報警,然後bug聯邦檢察院會起訴你。

為了讓問題更透明一些,我們修改一下結構體

struct person

~person()

};person* getperson2()

person *p2 = getperson2();

cout

這一次,函式結束後,物件的銷毀要比上一次徹底的多,雖然,www.cppcns.comage的區域還是沒有被徹底銷毀,但是name區域被徹底銷毀了,如果你訪問name的區域,就必然出錯,這就好比啊,私家花園關門了,可是花園好大的,所以不是每一處都安裝了攝像頭和報警器,比如age這片區域,所以,你偷偷的從age這個區域溜進去時,花園的主人沒發現,直到花園的巡防大隊到age區域巡防時,發現你竟然在這裡偷偷菜花,結果就是把你打的崩潰了。而name這邊區域,在~person這個析構函式中安裝了攝像頭和報警器,你只要來,就立刻報警,然後把你打的崩潰。

千言萬語,匯成一句話,函式不要返回指向棧的記憶體位址,切記,是位址,別被嚇的所有的函式內的變數都不敢返回,只要不是棧的記憶體位址,你儘管放心的返回。

C語言函式返回值為指標和函式返回值為void

有時遇到函式返回值為空和函式返回值為指標的情況下,需要在前面定義該函式 函式的返回值為指標也必須在此定義,函式的返回值為void必須在此定義,返回值是整形或者其他基本型別不需要在此定義 函式功能 把格式化的資料寫入某個字串 函式原型 int sprintf char buffer,const cha...

C 函式返回值為const

c 函式返回值為const 令函式返回值為const,往往可以降低因使用者錯誤而造成的意外,而又不至於放棄安全性和高效性。class rational class rational operator const rational lhs,const rational rhs rational a,b...

c 賦值(賦值為函式返回值)語句的返回值問題

不知道為什麼,之前一直腦子裡有乙個誤解,賦值語句的返回值應該是1 成功賦值 或0 賦值失敗 今天其實在學linux的時候突然揣摩了一下 才發現這個問題 if dir opendir home ljz desktop null opendir返回空說明目錄開啟失敗 這句 裡面 null的判斷在 dir...