亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解C++編譯器優(yōu)化技術

 更新時間:2021年06月07日 09:31:58   作者:可可西  
現代編譯器缺省會使用RVO(return value optimization,返回值優(yōu)化)、NRVO(named return value optimization、命名返回值優(yōu)化)和復制省略(Copy elision)技術,來減少拷貝次數來提升代碼的運行效率。

前言

注1:vc6、vs沒有提供編譯選項來關閉該優(yōu)化,無論是debug還是release都會進行RVO和復制省略優(yōu)化

注2:vc6、vs2005以下及vs2005+ Debug上不支持NRVO優(yōu)化,vs2005+ Release支持NRVO優(yōu)化

注3:g++支持這三種優(yōu)化,并且可通過編譯選項:-fno-elide-constructors來關閉優(yōu)化

RVO

#include <stdio.h>
class A
{
public:
    A()
    {
        printf("%p construct\n", this);
    }
    A(const A& cp)
    {
        printf("%p copy construct\n", this);
    }
    ~A() 
    {
        printf("%p destruct\n", this);
    }
};

A GetA()
{
    return A();
}

int main()
{
    {
        A a = GetA();
    }

    return 0;
}

在g++和vc6、vs中,上述代碼僅僅只會調用一次構造函數和析構函數 ,輸出結果如下:

0x7ffe9d1edd0f construct

0x7ffe9d1edd0f destruct

在g++中,加上-fno-elide-constructors選項關閉優(yōu)化后,輸出結果如下:

0x7ffc46947d4f construct  // 在函數GetA中,調用無參構造函數A()構造出一個臨時變量temp

0x7ffc46947d7f copy construct // 函數GetA return語句處,把臨時變量temp做為參數傳入并調用拷貝構造函數A(const A& cp)將返回值ret構造出來

0x7ffc46947d4f destruct // 函數GetA執(zhí)行完return語句后,臨時變量temp生命周期結束,調用其析構函數~A()

0x7ffc46947d7e copy construct // 函數GetA調用結束,返回上層main函數后,把返回值變量ret做為參數傳入并調用拷貝構造函數A(const A& cp)將變量A a構造出來

0x7ffc46947d7f destruct // A a = GetA()語句結束后,返回值ret生命周期結束,調用其析構函數~A()

0x7ffc46947d7e destruct // A a要離開作用域,生命周期結束,調用其析構函數~A()

注:臨時變量temp、返回值ret均為匿名變量

下面用c++代碼模擬一下其優(yōu)化行為:

#include <new>
A& GetA(void* p)
{
    //由于p的內存是從外部傳入的,函數返回后仍然有效,因此返回值可為A&
    //vs中,以下代碼還可以寫成:
    // A& o = *((A*)p);
    // o.A::A(); 
    // return o;
    return *new (p) A(); // placement new
}

int main()
{
    {
        char buf[sizeof(A)];
        A& a = GetA(buf);
        a.~A();
    }

    return 0;
}

NRVO

g++編譯器、vs2005+ Release(開啟/O2及以上優(yōu)化開關)

修改上述代碼,將GetA的實現修改成:

A GetA()
{
    A o;
    return o;
}

在g++、vs2005+ Release中,上述代碼也僅僅只會調用一次構造函數和析構函數 ,輸出結果如下:

0x7ffe9d1edd0f construct

0x7ffe9d1edd0f destruct

g++加上-fno-elide-constructors選項關閉優(yōu)化后,和上述結果一樣

0x7ffc46947d4f construct

0x7ffc46947d7f copy construct

0x7ffc46947d4f destruct

0x7ffc46947d7e copy construct

0x7ffc46947d7f destruct

0x7ffc46947d7e destruct

但在vc6、vs2005以下、vs2005+ Debug中,沒有進行NRVO優(yōu)化,輸出結果為:

18fec4 construct  // 在函數GetA中,調用無參構造函數A()構造出一個臨時變量o

18ff44 copy construct  // 函數GetA return語句處,把臨時變量o做為參數傳入并調用拷貝構造函數A(const A& cp)將返回值ret構造出來

18fec4 destruct  // 函數GetA執(zhí)行完return語句后,臨時變量o生命周期結束,調用其析構函數~A()

18ff44 destruct // A a要離開作用域,生命周期結束,調用其析構函數~A()

下面用c++代碼模擬一下vc6、vs2005以下、vs2005+ Debug上的行為:

#include <new>
A& GetA(void* p)
{
    A o;
    //由于p的內存是從外部傳入的,函數返回后仍然有效,因此返回值可為A&
    //vs中,以下代碼還可以寫成:
    // A& t = *((A*)p);
    // t.A::A(o); 
    // return t;
    return *new (p) A(o); // placement new
}

int main()
{
    {
        char buf[sizeof(A)];
        A& a = GetA(buf);
        a.~A();
    }

    return 0;
}

注:與g++、vs2005+ Release相比,vc6、vs2005以下、vs2005+ Debug只優(yōu)化掉了返回值到變量a的拷貝,命名局部變量o沒有被優(yōu)化掉,所以最后一共有2次構造和析構的調用

復制省略

典型情況是:調用構造函數進行值類型傳參

void Func(A a) 
{
}

int main()
{
    {
        Func(A());
    }

    return 0;
}

在g++和vc6、vs中,上述代碼僅僅只會調用一次構造函數和析構函數 ,輸出結果如下:

0x7ffeb5148d0f construct

0x7ffeb5148d0f destruct

在g++中,加上-fno-elide-constructors選項關閉優(yōu)化后,輸出結果如下:

0x7ffc53c141ef construct   // 在main函數中,調用無參構造函數構造實參變量o

0x7ffc53c141ee copy construct // 調用Func函數后,將實參變量o做為參數傳入并調用拷貝構造函數A(const A& cp)將形參變量a構造出來

0x7ffc53c141ee destruct // 函數Func執(zhí)行完后,形參變量a生命周期結束,調用其析構函數~A()

0x7ffc53c141ef destruct // 返回main函數后,實參變量o要離開作用域,生命周期結束,調用其析構函數~A()

下面用c++代碼模擬一下其優(yōu)化行為:

void Func(const A& a) 
{
}

int main()
{
    {
        Func(A());
    }

    return 0;
}

優(yōu)化失效的情況

開啟g++優(yōu)化,得到以下各種失效情況的輸出結果:

(1)根據不同的條件分支,返回不同變量

A GetA(bool bflag)
{
    A a1, a2;
    if (bflag)
        return a1;
    return a2;
}

int main()
{
    A a = GetA(true);

    return 0;
}

0x7ffc3cca324f construct

0x7ffc3cca324e construct

0x7ffc3cca327f copy construct

0x7ffc3cca324e destruct

0x7ffc3cca324f destruct

0x7ffc3cca327f destruct

注1:2次缺省構造函數調用:用于構造a1、a2

注2:1次拷貝構造函數調用:用于拷貝構造返回值

注3:這兒仍然用右值引用優(yōu)化掉了一次拷貝函數調用:返回值賦值給a

(2)返回參數變量

(3)返回全局變量

(4)返回復合數據類型中的成員變量

(5)返回值賦值給已構造好的變量(此時會調用operator==賦值運算符)

以上就是詳解C++編譯器優(yōu)化技術的詳細內容,更多關于C++編譯器優(yōu)化技術的資料請關注腳本之家其它相關文章!

相關文章

  • C?語言中布爾值的用法實戰(zhàn)案例

    C?語言中布爾值的用法實戰(zhàn)案例

    這篇文章主要為大家介紹了C語言中布爾值的用法實戰(zhàn)案例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • QT利用QPainter繪制三維餅狀圖

    QT利用QPainter繪制三維餅狀圖

    這篇文章主要為大家詳細介紹了如何利用QPainter實現三維餅狀圖的繪制,由于Qt中沒有三維餅狀圖的繪制組件,因此只能自行繪制,感興趣的可以動手嘗試一下
    2022-06-06
  • C/C++ Qt ToolBar菜單組件的具體使用

    C/C++ Qt ToolBar菜單組件的具體使用

    ToolBar工具欄在所有窗體應用程序中都廣泛被使用,使用ToolBar可以很好的規(guī)范菜單功能分類,本文就詳細的介紹一下ToolBar組件的應用,感興趣的可以了解一下
    2021-11-11
  • 如何讓C++函數返回值死心塌地為你工作

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

    這篇文章主要介紹了如何讓C++函數返回值死心塌地為你工作,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • C++編程面向對象入門全面詳解

    C++編程面向對象入門全面詳解

    這篇文章主要為大家介紹了C++面向對象入門的全面詳解,文章較長非常全面建議收藏閱讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10
  • C語言數據結構之單向鏈表詳解

    C語言數據結構之單向鏈表詳解

    單向鏈表(單鏈表)是鏈表的一種,其特點是鏈表的鏈接方向是單向的,對鏈表的訪問要通過順序讀取從頭部開始。本文將為大家詳細講講單向鏈表的實現與使用,需要的可以參考一下
    2022-08-08
  • 基于C++11的threadpool線程池(簡潔且可以帶任意多的參數)

    基于C++11的threadpool線程池(簡潔且可以帶任意多的參數)

    C++11 加入了線程庫,從此告別了標準庫不支持并發(fā)的歷史。然而 c++ 對于多線程的支持還是比較低級,稍微高級一點的用法都需要自己去實現,譬如線程池、信號量等
    2019-04-04
  • C語言實現超市信息管理系統(tǒng)課程設計

    C語言實現超市信息管理系統(tǒng)課程設計

    這篇文章主要為大家詳細介紹了C語言實現超市信息管理系統(tǒng)課程設計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Qt數據庫應用之實現通用數據生成器

    Qt數據庫應用之實現通用數據生成器

    有兩種應用場景需要用到數據生成器,一種是需要測試數據庫性能,一種是隨機模擬生成一堆數據,用來測試程序的性能。本文將利用Qt實現通用數據生成器,需要的可以參考一下
    2022-02-02
  • 淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr

    淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr

    雖然通過弱引用指針可以有效的解除循環(huán)引用,但這種方式必須在程序員能預見會出現循環(huán)引用的情況下才能使用,也可以是說這個僅僅是一種編譯期的解決方案,如果程序在運行過程中出現了循環(huán)引用,還是會造成內存泄漏的
    2013-09-09

最新評論