<kbd id="daqct"></kbd>

  • <nav id="daqct"></nav>
    <wbr id="daqct"><pre id="daqct"></pre></wbr>
    <wbr id="daqct"></wbr>
    <form id="daqct"><th id="daqct"></th></form>
    更多課程 選擇中心

    C/C++培訓
    達內IT學院

    400-111-8989

    C++中的返回值優化

    • 發布:C++培訓
    • 來源:資料庫
    • 時間:2017-10-10 14:08

    在這篇文章里用到了以下編譯器和操作系統,大家請自行安裝

    首先我們先來看一道題,下面的代碼運行之后會輸出什么結果?

    我想大多數人會選A,對嗎?因為foo函數在返回C類的對象時會調用拷貝構造函數來創建一個臨時對象。

    現在讓我們編譯并運行這個程序,看看輸出結果是否如我們所料

    $ clang++ -std=c++11 foo.cpp

    $ ./a.out

    Constructor

    Destructor

    然而,遺憾的是,事實與課本里說的并不一樣,那么,為什么會這樣呢?從實際編譯運行的輸出來看,C類的拷貝構造函數并沒有被調用。

    這是因為在實際工程中大多數時候C++構造對象的開銷巨大,編譯器為了生成高效的代碼,在foo函數返回時并沒有調用拷貝構造函數去生成一個臨時對象,而是直接使用在foo函數內初始化的對象c1作為返回值傳出去。這就是C++中的返回值優化(Return Value Optimization, RVO)。

    由于較新版本的gcc/clang均已默認開啟了返回值優化(即使沒有加上優化選項),我們想看到書上所說的現象只能在編譯的時候加上特殊選項,讓編譯器不要做返回值優化,操作步驟如下:

    $ clang++ -std=c++11 -fno-elide-constructors foo.cpp

    $ ./a.out

    Constructor

    Copy Constructor

    Destructor

    Destructor

    返回值優化能在一定程度上提高程序的運行效率,但是我們在實際工程中最好不要依賴這個編譯器優化特性,因為它要求的條件非常苛刻(或者說,編譯器還不夠聰明:P)。讓我們在foo函數中加上一個無用的條件判斷語句,試試編譯器是否能繼續應用返回值優化。

    可以發現,在上面的代碼中,如果編譯器足夠聰明,它應該能推斷出foo函數只會返回c1,所以可以對foo函數應用返回值優化,那么讓我們來實際編譯運行一下,看看執行情況。

    $ clang++ -std=c++11 -O3 foo.cpp

    $ ./a.out

    Constructor

    Constructor

    Copy Constructor

    Destructor

    Destructor

    Destructor

    $ g++ -std=c++11 -O3 foo.cpp

    $ ./a.out

    Constructor

    Constructor

    Copy Constructor

    Destructor

    Destructor

    Destructor

    可以看到,clang 5.0.0和gcc 6.3.0即使把優化選項開到最大也不能對foo函數進行返回值優化。

    返回值優化還帶來了一個問題,那就是拷貝構造函數和析構函數的調用變得不可預測。如果在拷貝構造函數和析構函數中存在有副作用(side-effect)的語句,就會造成不同的編譯器配置編譯出來的程序運行結果不一致。事實上,這是被C++11標準所允許的,下面這段話引用自C++11標準Sec 12.8 Copying and moving class objects [class.copy]

    When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects.

    是否調用拷貝構造函數和析構函數的決定交給了編譯器實現去判斷,所以在實際工程中為了寫出可移植的代碼,就需要避免在構造函數和析構函數中加入有副作用的語句,并且應該盡量把復雜的邏輯剝離出來,放在類的其它成員函數中實現。

    原文鏈接:https://hackmd.io/s/BynCMibnW

    預約申請免費試聽課

    填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

    上一篇:教你如何養成良好的C++開發代碼風格
    下一篇:達內C++培訓班:教你C/C++回調函數

    超全的C語言標識符知識

    C指針——指針類型轉換

    C指針——指針和結構類型的關系

    C指針——數組和指針的關系

    • 掃碼領取資料

      回復關鍵字:視頻資料

      免費領取 達內課程視頻學習資料

    • 視頻學習QQ群

      添加QQ群:1143617948

      免費領取達內課程視頻學習資料

    Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

    選擇城市和中心
    黑龍江省

    吉林省

    河北省

    湖南省

    貴州省

    云南省

    廣西省

    海南省

    欧美三级片,白洁外传,第四色播日韩AV第一页,啪啪免费观看大全av 百度 好搜 搜狗
    <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>