如何讓C++函數(shù)返回值死心塌地為你工作
本文主要研究的是C++函數(shù)返回值,你必須注意的問題,下面進入正題。
C++太繁雜了,先接觸C++后接觸python這樣的語言,你就再也不想碰它,因為,就連一個函數(shù)返回值都一大堆的說道,這里面的玄機,連工作三年的C++熟手都未必能準(zhǔn)確的理解和運用。
歸根結(jié)底,C++所面臨的問題要求它提供各種各樣的機制以保證性能,也許,這輩子也見不到C++能安全有效的自己進行內(nèi)存垃圾回收。。。。。
老程序猿都會提醒菜鳥,注意函數(shù)的返回值,因為,很可能,你的函數(shù)返回的數(shù)據(jù)在后續(xù)的使用中會出錯。那么函數(shù)在返回值時要注意什么呢?
本篇博客嘗試用最簡練的普通大白話,講解函數(shù)返回值的問題。
C++把內(nèi)存交給了程序猿,但是,請你注意,它可沒把所有的內(nèi)存都交給你,交給你的只是堆上的內(nèi)存,也就是你通過malloc函數(shù) 和new 關(guān)鍵字申請來的內(nèi)存,除了這些內(nèi)存以外,其他的內(nèi)存,你最好別碰,最好別碰,最好別碰,重要的事情說三遍。
如果你的函數(shù)返回值在后續(xù)使用中出錯了,尤其是返回函數(shù)內(nèi)的局部變量這種事情,那么,基本可以肯定,你碰了不該碰的內(nèi)存。這時候,你會覺得自己很冤枉啊,我沒有啊。但事實是,沒有冤枉你,所以,為了不被bug檢察院起訴你,作為一個C++程序猿,你必須學(xué)會甄別那些內(nèi)存是能碰的,那些內(nèi)存是不能碰的。
char *pstr = "This is the buffer text"; return pstr;
如果你的函數(shù)是這么寫的,那么恭喜你,返回正確,因為這個pstr指向的是常量存儲區(qū),這里的內(nèi)存,你是可以碰的,但是注意,這個碰,僅僅是讀,你想修改,那是萬萬不可以的。
char buffer[] = "This is the buffer text"; return buffer;
如果你的函數(shù)是這么寫的,那么恭喜你,等著bug聯(lián)邦檢察院起訴你吧。這里的buffer指向的是棧上內(nèi)存,這個,就是你碰不得的,前面的pstr就好比公園,公園嘛,大家都可以來玩,但是你不能把公園里的假山拆了,你也不能把公園里的樹砍了,你只能是來玩,不能修改它,棧上的內(nèi)存,就好比是私家花園,你一個外人,是不能進去的。那么怎么甄別的,方法倒也簡單,你見到帶中括號的,就應(yīng)該明白,這東西是棧上的,出了這個函數(shù),你就別想再碰的,你只要敢碰,bug聯(lián)邦檢察院就會起訴你。
static char buffer[] = "This is the buffer text"; return buffer;
如果你的函數(shù)是這么寫的,那么恭喜你,返回正確,可是剛才不是明明說,這里是私家花園嘛,沒錯,但是你注意看,前面還加了一個static,只要加了這個關(guān)鍵字,就相當(dāng)于說國家把這個私家花園征用了,那么,它就從私家花園變成了靜態(tài)存儲區(qū)里的一個小花園,靜態(tài)存儲區(qū)里的內(nèi)存,國家說,靜態(tài)存儲區(qū)對外開放,你們都可以來。
函數(shù)返回的都是值拷貝,棧上的內(nèi)存,在函數(shù)結(jié)束的時候,都會被收回。在函數(shù)內(nèi)部,你可以碰棧上的內(nèi)存,那是因為這個時候你是在棧的家里做客,那他們家的內(nèi)存小花園當(dāng)然允許你訪問,可是函數(shù)結(jié)束了,就相當(dāng)于你離開了棧的家,棧把內(nèi)存小花園的門關(guān)上了,你怎么可以進去,你進去了,就會被bug聯(lián)邦法院起訴!
但是呢,總有一些奇怪的現(xiàn)象讓你以為你可以在函數(shù)結(jié)束后仍然可以訪問棧上的內(nèi)存。
我們定義一個結(jié)構(gòu)體
struct person
{
int age;
}
寫一個函數(shù)
person* getperson2()
{
person p;
p.age = 99;
return &p;
}
在得到函數(shù)的返回值以后,你可以輸出對象的年齡
person *p2 = getperson2(); cout<<p2->age<<endl;
你會發(fā)現(xiàn),這段代碼居然可以正確執(zhí)行!在函數(shù)getperson2內(nèi)部,p這個變量是局部變量,必然是在棧上申請的,返回的是&p,這不就是棧上的內(nèi)存地址么,那為啥在函數(shù)外部,卻仍然可以輸出age呢?
雖然,函數(shù)結(jié)束后,對象被銷毀,但是銷毀的不夠徹底,似乎計算機在管理內(nèi)存時也不需要那么徹底的銷毀一個對象,你之所以能輸出age,那是因為那個區(qū)域,沒有被徹底銷毀,這一小塊的內(nèi)存(存儲age的4個byte)沒有發(fā)生變化。你可以暫時的碰這塊內(nèi)存,但遲早是要出問題的,如果某一刻,計算機打算用這塊內(nèi)存,發(fā)現(xiàn)你在非法使用,那么必然會報警,然后bug聯(lián)邦檢察院會起訴你。
為了讓問題更透明一些,我們修改一下結(jié)構(gòu)體
struct person
{
int age;
char* name;
person()
{
name = new char(10);
strcpy(name,"sheng");
}
~person()
{
name = NULL;
}
};
person* getperson2()
{
person p;
p.age = 99;
return &p;
}
person *p2 = getperson2(); cout<<p2->age<<endl; cout<<p2->name<<endl;
這一次,函數(shù)結(jié)束后,對象的銷毀要比上一次徹底的多,雖然,age的區(qū)域還是沒有被徹底銷毀,但是name區(qū)域被徹底銷毀了,如果你訪問name的區(qū)域,就必然出錯,這就好比啊,私家花園關(guān)門了,可是花園好大的,所以不是每一處都安裝了攝像頭和報警器,比如age這片區(qū)域,所以,你偷偷的從age這個區(qū)域溜進去時,花園的主人沒發(fā)現(xiàn),直到花園的巡防大隊到age區(qū)域巡防時,發(fā)現(xiàn)你竟然在這里偷偷菜花,結(jié)果就是把你打的崩潰了。而name這邊區(qū)域,在~person這個析構(gòu)函數(shù)中安裝了攝像頭和報警器,你只要來,就立刻報警,然后把你打的崩潰。
千言萬語,匯成一句話,函數(shù)不要返回指向棧的內(nèi)存地址,切記,是地址,別被嚇的所有的函數(shù)內(nèi)的變量都不敢返回,只要不是棧的內(nèi)存地址,你盡管放心的返回。
以上就是本文關(guān)于如何讓C++函數(shù)返回值死心塌地為你工作的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10如何判斷一個數(shù)是否為2的冪次方?若是,并判斷出來是多少次方
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10如何判斷一個數(shù)是否為4的冪次方?若是,并判斷出來是多少次方
- 01-10如何查看進程實際的內(nèi)存占用情況詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)
- 01-10用C++實現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實現(xiàn)與遞歸實現(xiàn)的方法(C++)


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實例總結(jié)
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 01-11ajax實現(xiàn)頁面的局部加載


