国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

C++中返回的引用

發布時間:2011-4-7 21:09    發布者:1640190015
大家都知道一個常識:“千萬不要返回局部對象或變量的引用和指針”。
     既然所有C++權威的書上都要求“一定不要返回局部對象或變量的引用和指針”,那為什么C++編譯器不從語法上直接禁掉這種用法,讓你編譯通不過(在技術上應該不難實現的)。如果只是建議的話,那么“返回局部對象或變量的引用和指針”是否有用武之地呢?(從理論上來講,我認為這種做法似乎總是錯誤的,原因大家都知道。)
    EX(1)
    #include
    using namespace std;
    class CComplex
    {
    public:
    CComplex():real(0),image(0){}
    CComplex(double real,double image):real(real),image(image){}
    CComplex& operator+(const CComplex& second)
    {
    CComplex temp(real+second.real,image+second.image);
    return temp;
    }
    void Print()
    {
    cout《"("《real《"+"《image《"i)"《endl;
    }
    private:
    double real;
    double image;
    };
    int main()
    {
    CComplex a(2,4);
    CComplex b(1.5,3.5);
    CComplex c=a+b;
    c.Print();
    return 0;
    }
    operator+返回的是臨時對象的引用,為什么能正確地工作???
    EX(2)
    #include
    #include
    using namespace std;
    string& f()
    {
    string s("hello");
    return s;
    }
    int main()
    {
    cout《f()《endl;
    return 0;
    }
    同樣是對象,為什么string對象就不行,就因為string比較特殊???
    EX(3)
    #include
    #include
    using namespace std;
    double& f()
    {
    double d(5.55);
    return d;
    }
    int main()
    {
    cout《f()《endl;
    return 0;
    }
    為什么內置類型(int,float等均可)返回局部變量的引用總可以正確地工作???
    這個問題似乎以前已經有人討論過,但一直沒有定論。
    不要跟我說運行正確是因為我運氣好,運氣不好地話就輸出任意值;
    我運行了N次,未見任何異常,也不要說運行上千萬次才有可能出問題;
    我在GCC和VS2010上都驗證過了,我覺得是不是編譯器做了相應的優化啊(特別是針對內置基本類型)。
    有想法的兄弟望賜教,感激不盡!!
    int main()
    {
    CComplex a(2,4);
    CComplex b(1.5,3.5);
    CComplex c=a+b;
    c.Print();
    return 0;
    }
    operator+返回的是臨時對象的引用,為什么能正確地工作???
    答:main函數在執行之后,a,b入棧,接著a+b調用了operator+,temp也入棧,operator+執行完后,temp出棧并調用析構函數,由于出棧僅僅是移動了PC指針,而你又未寫析構函數將CComplex清零,因此temp所占的那塊棧空間的內存依然保持原樣,只是PC指針已經不再指向它,而operator+返回的引用其實指向的是temp所占內存,然后在調用CComplex的默認拷貝構造的函數的時候,由于拷貝構造函數的輸入參數也是引用,因此也指向temp那塊內存,對此快內存也會按照CComplex類型來進行訪問,最后c就得到了temp的內容。這里即使是寫成CComplex& c=a+b;結果也是能輸出temp的內容的。此時你若在此句話后面再加幾個函數調用,這些函數必須要有參數或內部定義有變量,然后再c.Print(),你會發現結果完全變了。
    EX(2)
    #include
    #include
    using namespace std;
    string& f()
    {
    string s("hello");
    return s;
    }
    int main()
    {
    cout《f()《endl;
    return 0;
    }
    同樣是對象,為什么string對象就不行,就因為string比較特殊???
    答:因為s在出棧的時候其析構函數會將內存都清掉,在外面還想訪問自然訪問不成功了。
    EX(3)
    #include
    #include
    using namespace std;
    double& f()
    {
    double d(5.55);
    return d;
    }
    int main()
    {
    cout《f()《endl;
    return 0;
    }
    答:理解了上面兩個答案,這個我就不用多說了吧。
    每個人必有其背后的深刻原因,只是受限于種種因素,人們不可能都去搞明白。更多時候,并不是原因不充分,只是人們以其自己的知識背景還不足以理解。
    一、為什么不禁用的問題
    為什么不禁引用返回局部變量,技術上真的是不難嗎?且,有足夠的必要嗎?請見以下例子:
    int *f1(int &ri)
    {
    return &ri;
    }
    int *f2()
    {
    int i=4;
    int *j;
    j=f1(i);
    return j;
    }
    int main()
    {
    int *p=f2();
    *p=6;
    return 0;
    }
    p在初始化后,*p生命期是否已經結束了呢?我相信,如果這件事也得由編譯器去判斷,那么顯然,程序員全部可以下崗了,編譯器實在是太智能了,人還有必要存在嗎?但現有技術真的能嗎?如果能的話,要花多大開銷,這個開銷有必要嗎?“千萬不要返回局部對象或變量的引用和指針”應該是個原則性的東西,它是個典型代表,其實大原則是“不要在自動變量(不管是表達式中間結果的臨時變量(如果它不能保證總優化到寄存器中)還是源程序中有明確名字的auto變量)生命期結束后還試圖解引用它”。
    程序設計語言課一般會說語言的可寫性與可讀性是對矛盾,C語言的可寫性特別強,既會給比較強的人非常靈活的選擇,又會讓入門者走不少彎路或者半途而廢。利器不是誰都能用得好,這與水平不水平沒什么關系,說人的水平不足夠使用C++,當然也可以站在沒有學會用C++的人的立場,說C++太過于復雜,以至大多數人是學不會用不好的,但它的每個設計的確都有它的現實考慮,編程語言是很實在的東西,往往外貌冷冰冰但其為什么是這樣有充足原因。
    二、你的好運氣
    你要是明白函數調用時局部變量是如何入棧出棧的,看看反匯編的代碼,并跟蹤一下堆棧的變化情況,你會設計出一個讓值產生變化的例子。如果這類錯誤后,導致被改變的值,并不是指針的值,則在這么小的程序中,系統不一定都崩潰,它不過是讓部分你沒照顧到的地方變了變值,卻沒有影響輸出。
    建議樓主閱讀一下TCPL有關臨時變量一節,看看各種條件下生成的臨時變量的作用域,與給出名字的局部變量間,有何差同。
    三、其他一些為什么的例子
    關于C++的為什么特別多,如果你不是經驗豐富且善于思考,是很難理解為什么有這么多為什么的。當然,為什么的多少,是個程度問題,有差異存在的地方就有程度問題,不同的人善用不同的東西,C++是“小眾”的,但還不至于只是幾個人的,畢竟TIOBE還排第3。
    1.operator重載的解析順序為什么如現在標準那樣設計?是權衡了使用者的方便,和編譯器的效率之間的一種平衡,它過度自由帶來的是呈指數級上升的編譯時開銷,且該開銷并不一定值得。
    2.內置數組,為什么不設置下標檢測?如果檢測下標,定然就會在每次訪問下標時,做是否越界的檢驗,這就帶來了運行時開銷。如果你的算法非常好,定然不需要檢測下標,則語言假定一定要在每次訪問下標時都判斷,就會影響效率并失去選擇的機會。如果設置N個選項,可以用來關閉或打開是否檢測下標,那不應該是一種語言應該干的,各有各的側重點。
    3.C語言傳數組參數為什么默認是轉換成指針類型?以C語言產生那個年代的硬件條件,復制數組很奢侈,尤其函數被調用往往很頻繁,算法要盡量往不復制的情況下設計,如果實在必要,非要復制,你也可以手動memcpy嘛!總之它不是默認項。C++給了用戶另一種選項,即通過加上引用,而使得能夠真正傳整個數組,不過這都是很多年以后的事了。
    4.for語句為什么有的靈活有的嚴格?像在Ada中的語法,便是禁止循環變量被改變,且不能設置步長值,要想達到這兩個目的,便只能用其他變量再過渡,這樣做是為了高度的安全。反之,C語言的for則非常靈活,也沒有Ada那么多的限制,但這種靈活并不能保證用戶用其寫出錯誤邏輯的代碼;VB的自由度則介于二者之間。不能因為這些語言的設計不同,而指責其中某一種語言為何不對某一語法特性做必要的限制,它真的必要嗎?個案好說,但綜合全局,很難評估。
    四、設計者們不傻
    且任何有影響力的技術,其規范,都是經過全球大量從業者多年實踐后,總結整理并論證出來的,并不是一個或幾個人拍拍腦袋就草率決定的,因此C++的新標準化過程要歷時8年之久。Bjarne Stroustrup不傻,Herb Sutter, Stanley Lippman, Scott Meyer, Alexander Stepanov, Andrew Koenig等人也不傻,標準委員會都不是白給的,大多數細節問題早就被提出過。具體實現,要難得多,這點語法層面上的皮毛問題,都不值一提。
本文地址:http://m.qingdxww.cn/thread-61370-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
sw9518 發表于 2011-4-21 09:22:45
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 更佳設計的解決方案——Microchip模擬開發生態系統
  • 想要避免發生災難,就用MPLAB SiC電源仿真器!
  • 利用模擬開發工具生態系統進行安全電路設計
  • Cortex-M4外設 —— TC&TCC結合事件系統&DMA優化任務培訓教程
  • 貿澤電子(Mouser)專區
關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 99精品这里只有精品高清视频 | 91色在线视频 | 久久香蕉国产精品一区二区三 | 成人三级视频在线观看 | 色99在线| 露脸国产精品自产在线播 | 亚洲免费网址 | 一二三四视频社区5在线高清视频 | 国产精品视频久 | 韩国一级成a人片在线观看 韩国一级a毛片 | 九九热最新网址 | 日韩亚洲欧洲在线rrrr片 | free俄罗斯性xxxx | 91亚洲精品在看在线观看高清 | 99热这里只有精品第一页 | 黄色欧美视频在线观看 | 黄页网站免费视频 | 韩国伦理妈妈的朋友在线观看 | 最近韩国日本免费观看 | 日韩一级片免费观看 | 污污网站免费观看 | 欧美一级欧美一级在线播放 | 色猫成人网 | 日韩欧美第一区二区三区 | 狠狠狠色丁香婷婷综合久久88 | 国产高清成人 | 敢死队4免费播放完整版 | jizz日本人 | 欧美一区二区三区播放 | 国产精品国产三级农村妇女 | 大伊香蕉精品视频在线观看 | 91精品综合国产在线观看 | 美女网站免费福利视频 | 四虎4hu永久在线观看 | 岛国片在线免费观看 | 操熟逼| 亚洲乱码在线视频 | 九一国产在线观看免费 | 青青免费 | 欧美性色黄大片在线观看 | 性俄罗斯hd |