中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++引用與內聯函數怎么使用

發布時間:2023-03-07 11:39:31 來源:億速云 閱讀:95 作者:iii 欄目:開發技術

這篇文章主要介紹“C++引用與內聯函數怎么使用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“C++引用與內聯函數怎么使用”文章能幫助大家解決問題。

    一、引用

    首先我們來看一下引用的概念:

    1.1引用的概念

    引用不是新定義一個變量,而是給已存在變量取了一個別名,編譯器不會為引用變量開辟內存空間,它和它引用的變量共用同一塊內存空間。

    類型& 引用變量名(對象名) = 引用實體;

    1.1.1代碼展示
    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    using namespace std;
    int main()
    {
    	int i = 0;
    	int& k = i; // 這里的k就是變量i的引用,可以理解為k是i的一個別名
    				//這里的k和i可以理解為同一個空間
    	int j = i;//這里的j是一個全新的變量,是將變量i的值賦給了j
    
    	cout << &i << endl;
    	cout << &k << endl;
    	cout << &j << endl;
    	++k;
    	++j;
    	int& m = i;
    	int& n = k;
    	++n;
    	return 0;
    }
    1.1.2圖示

    C++引用與內聯函數怎么使用

    我們可以結合上圖分析代碼,k是i的引用,可以理解為k是i的別名,就比如宋江和宋公明,名字看起來不一樣但是是同一個人,這里的k和i是同一個空間,k和i任何一個的變化都會影響另外一個變量的變化。

    我們再來看一下三個變量的地址:

    C++引用與內聯函數怎么使用

    我們發現三個變量中i,k兩個變量的地址完全相同,所以說明k沒有實際開辟空間,只是i變量的一個別名而已。

    我們在C語言中有一種特殊情況:二級指針,因為我們都直到形參的改變不會影響到實參,如果我們想在形參變化的時候讓實參也變化就得地址傳遞,操作同一塊空間,我們C++就可以利用引用來解決這一問題,我們直接讓形式參數是實參的別名就好。

    注意:引用類型必須和引用實體是同種類型的

    1.2引用的特性

    • 引用在定義時必須初始化

    • 一個變量可以有多個引用

    • 引用一旦引用一個實體,再不能引用其他實體

    void TestRef()
    {
       int a = 10;
       // int& ra;   // 該條語句編譯時會出錯,因為沒有初始化
       int& ra = a;
       int& rra = a;
       printf("%p %p %p\n", &a, &ra, &rra);  
    }

    1.3常引用

    void TestConstRef()
    {
        const int a = 10;
        //int& ra = a;   // 該語句編譯時會出錯,a為常量
        const int& ra = a;
        // int& b = 10; // 該語句編譯時會出錯,b為常量
        const int& b = 10;
        double d = 12.34;
        //int& rd = d; // 該語句編譯時會出錯,類型不同
        const int& rd = d;
    }

    1.4引用的使用場景

    1.做參數

    void Swap(int& left, int& right)
    {
       int temp = left;
       left = right;
       right = temp;
    }

    &emsp;&emsp;做參數就是為了解決形參的改變不影響實參這個問題,我們在C語言中想要做到輸出型參數,就得利用指針來實現,但是在C++中我們就可以用引用做參數,我們的形參就是實參的別名,這里一旦形參發生了改變實參也會發生相應的改變,也就是說這里是輸出型參數。

    2.做返回值

    int& Count()
    {
       static int n = 0;
       n++;
       // ...
       return n;
    }

    我們先來看一下普通函數的調用:

    C++引用與內聯函數怎么使用

    C++引用與內聯函數怎么使用

    C++引用與內聯函數怎么使用

    但是我們再來分析一下下面的代碼:

    C++引用與內聯函數怎么使用

    C++引用與內聯函數怎么使用

    如果還給了操作系統還使用傳引用返回,那么結果就是未定義的

    1.5 傳值、傳引用效率比較

    以值作為參數或者返回值類型,在傳參和返回期間,函數不會直接傳遞實參或者將變量本身直接返回,而是傳遞實參或者返回變量的一份臨時的拷貝,因此用值作為參數或者返回值類型,效率是非常低下的,尤其是當參數或者返回值類型非常大時,效率就更低。
    我們可以測試一下他們的效率:

    1.值和引用的作為函數參數的性能比較:

    #include <time.h>
    struct A{ int a[10000]; };
    void TestFunc1(A a){}
    void TestFunc2(A& a){}
    void TestRefAndValue()
    {
     A a;
     // 以值作為函數參數
     size_t begin1 = clock();
     for (size_t i = 0; i < 10000; ++i)
     TestFunc1(a);
     size_t end1 = clock();
     // 以引用作為函數參數
     size_t begin2 = clock();
     for (size_t i = 0; i < 10000; ++i)
     TestFunc2(a);
     size_t end2 = clock();
    // 分別計算兩個函數運行結束后的時間
     cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
     cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
    }

    C++引用與內聯函數怎么使用

    2. 值和引用的作為返回值類型的性能比較

    #include <time.h>
    struct A{ int a[10000]; };
    A a;
    // 值返回
    A TestFunc1() { return a;}
    // 引用返回
    A& TestFunc2(){ return a;}
    void TestReturnByRefOrValue()
    {
     // 以值作為函數的返回值類型
     size_t begin1 = clock();
     for (size_t i = 0; i < 100000; ++i)
     TestFunc1();
     size_t end1 = clock();
     // 以引用作為函數的返回值類型
     size_t begin2 = clock();
     for (size_t i = 0; i < 100000; ++i)
     TestFunc2();
     size_t end2 = clock();
     // 計算兩個函數運算完成之后的時間
     cout << "TestFunc1 time:" << end1 - begin1 << endl;
     cout << "TestFunc2 time:" << end2 - begin2 << endl;
    }

    通過上述代碼的比較,發現傳值和指針在作為傳參以及返回值類型上效率相差很大。

    1.6 引用和指針的區別

    在語法概念上引用就是一個別名,沒有獨立空間,和其引用實體共用同一塊空間,

    int main()
    {
    int a = 10;
    int& ra = a;
    cout<<"&a = "<<&a<<endl;
    cout<<"&ra = "<<&ra<<endl;
    return 0;
    }

    在底層實現上實際是有空間的,因為引用是按照指針方式來實現的。

    int main()
    {
    int a = 10;
    int& ra = a;
    ra = 20;
    int* pa = &a;
    *pa = 20;
    return 0;
    }

    我們來看下引用和指針的匯編代碼對比:

    C++引用與內聯函數怎么使用

    引用和指針的不同點:

    1. 引用概念上定義一個變量的別名,指針存儲一個變量地址。

    2. 引用在定義時必須初始化,指針沒有要求

    3. 引用在初始化時引用一個實體后,就不能再引用其他實體,而指針可以在任何時候指向任何
      一個同類型實體

    4. 沒有NULL引用,但有NULL指針

    5. 在sizeof中含義不同:引用結果為引用類型的大小,但指針始終是地址空間所占字節個數(32位平臺下占4個字節)

    6. 引用自加即引用的實體增加1,指針自加即指針向后偏移一個類型的大小

    7. 有多級指針,但是沒有多級引用

    8. 訪問實體方式不同,指針需要顯式解引用,引用編譯器自己處理

    9. 引用比指針使用起來相對更安全

    二、內聯函數

    2.1.內聯函數的概念

    &emsp;&emsp;以inline修飾的函數叫做內聯函數,編譯時C++編譯器會在調用內聯函數的地方展開,沒有函數調用建立棧幀的開銷,內聯函數提升程序運行的效率。

    注意:C++推薦用const和enum替代宏常量用inline去替代宏函數

    C++引用與內聯函數怎么使用

    &emsp;&emsp;在c語言中宏是在預處理階段直接替換的,所以對于宏函數來說,是替換而不是調用,所以優點就是可以節省時間,因為不用調用函數建立棧幀。

    我們來看一下什么是宏函數:

    #define ADD(x, y) ((x)+(y)) //這個就是宏函數

    我們來解釋一下為什么它的形式是((x)+(y))

    int main()
    {
    	ADD(1, 2) * 3; // ((1)+(2))*3;
    	//上面就是解釋了為什么外面有一對括號
    	int a = 1, b = 2;
    	ADD(a | b, a & b); // ((a | b) + (a & b));;
    	//這里就解釋了為什么x和y要單獨括起來
    	return 0;
    }

    我們來看一下普通函數的調用在匯編代碼下的情況:

    C++引用與內聯函數怎么使用

    &emsp;&emsp;如果在上述函數前增加inline關鍵字將其改成內聯函數,在編譯期間編譯器會用函數體替換函數的調用。

    查看方式:

    • 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add

    • 在debug模式下,需要對編譯器進行設置,否則不會展開(因為debug模式下,編譯器默認不會對代碼進行優化,以下給出vs2019的設置方式)

    C++引用與內聯函數怎么使用

    C++引用與內聯函數怎么使用

    C++引用與內聯函數怎么使用

    2.2內聯函數的特性

    1. inline是一種以空間換時間的做法,如果編譯器將函數當成內聯函數處理,在編譯階段,會用函數體替換函數調用,缺陷:可能會使目標文件變大,優勢:少了調用開銷,提高程序運行效率。

    2. inline對于編譯器而言只是一個建議,不同編譯器關于inline實現機制可能不同,一般建議:將函數規模較小(即函數不是很長,具體沒有準確的說法,取決于編譯器內部實現)、不是遞歸、且頻繁調用的函數采用inline修飾,否則編譯器會忽略inline特性。
      《C++prime》第五版關于inline的建議:
      內聯函數只是向編譯器發送的一個請求,編譯器可以忽略這個請求
      一般來說,內聯機制用于優化規模較小,流程直接,頻繁調用的函數,很多編譯器都不支持內聯遞歸函數,而且一個75行的函數也不太可能在調用點內聯的展開。

    3. inline不建議聲明和定義分離,分離會導致鏈接錯誤。因為inline被展開,就沒有函數地址了,鏈接就會找不到

    // F.h
    #include <iostream>
    using namespace std;
    inline void f(int i);
    // F.cpp
    #include "F.h"
    void f(int i)
    {
     cout << i << endl;
    }
    // main.cpp
    #include "F.h"
    int main()
    {
     f(10);
     return 0;
    }
    // 鏈接錯誤:main.obj : error LNK2019: 無法解析的外部符號 "void __cdecl 
    f(int)" (?f@@YAXH@Z),該符號在函數 _main 中被引用

    關于“C++引用與內聯函數怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    c++
    AI

    上犹县| 枝江市| 东源县| 垦利县| 金平| 航空| 望江县| 广德县| 新巴尔虎右旗| 大厂| 西平县| 建阳市| 沿河| 湖北省| 玉田县| 金阳县| 凤凰县| 辽中县| 浦北县| 维西| 湖北省| 乌拉特中旗| 秦安县| 长治市| 光泽县| 获嘉县| 雷山县| 司法| 阿拉善盟| 保靖县| 荆州市| 阿坝县| 龙陵县| 浦县| 濮阳县| 遂昌县| 永康市| 浑源县| 镇巴县| 岳阳市| 澜沧|