最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一步步從底層入手搞定C++引用與內(nèi)聯(lián)函數(shù)

 更新時間:2023年03月07日 10:46:07   作者:暴躁小程序猿  
內(nèi)聯(lián)函數(shù)是代碼插入到調(diào)用者代碼處的函數(shù),內(nèi)聯(lián)函數(shù)通過避免被調(diào)用的開銷來提高執(zhí)行效率,下面這篇文章主要給大家介紹了關(guān)于如何從底層入手搞定C++引用與內(nèi)聯(lián)函數(shù)的相關(guān)資料,需要的朋友可以參考下

一、引用

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

1.1引用的概念

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

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

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圖示

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

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

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

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

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

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.做參數(shù)

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

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

2.做返回值

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

我們先來看一下普通函數(shù)的調(diào)用:

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

如果還給了操作系統(tǒng)還使用傳引用返回,那么結(jié)果就是未定義的

1.5 傳值、傳引用效率比較

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

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

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

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

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

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

1.6 引用和指針的區(qū)別

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

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

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

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

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

引用和指針的不同點:

  1. 引用概念上定義一個變量的別名,指針存儲一個變量地址。
  2. 引用在定義時必須初始化,指針沒有要求
  3. 引用在初始化時引用一個實體后,就不能再引用其他實體,而指針可以在任何時候指向任何
    一個同類型實體
  4. 沒有NULL引用,但有NULL指針
  5. 在sizeof中含義不同:引用結(jié)果為引用類型的大小,但指針始終是地址空間所占字節(jié)個數(shù)(32位平臺下占4個字節(jié))
  6. 引用自加即引用的實體增加1,指針自加即指針向后偏移一個類型的大小
  7. 有多級指針,但是沒有多級引用
  8. 訪問實體方式不同,指針需要顯式解引用,引用編譯器自己處理
  9. 引用比指針使用起來相對更安全

二、內(nèi)聯(lián)函數(shù)

2.1.內(nèi)聯(lián)函數(shù)的概念

  以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時C++編譯器會在調(diào)用內(nèi)聯(lián)函數(shù)的地方展開,沒有函數(shù)調(diào)用建立棧幀的開銷,內(nèi)聯(lián)函數(shù)提升程序運行的效率。

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

  在c語言中宏是在預(yù)處理階段直接替換的,所以對于宏函數(shù)來說,是替換而不是調(diào)用,所以優(yōu)點就是可以節(jié)省時間,因為不用調(diào)用函數(shù)建立棧幀。

我們來看一下什么是宏函數(shù):

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

我們來解釋一下為什么它的形式是((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;
}

我們來看一下普通函數(shù)的調(diào)用在匯編代碼下的情況:

  如果在上述函數(shù)前增加inline關(guān)鍵字將其改成內(nèi)聯(lián)函數(shù),在編譯期間編譯器會用函數(shù)體替換函數(shù)的調(diào)用。

查看方式:

  • 在release模式下,查看編譯器生成的匯編代碼中是否存在call Add
  • 在debug模式下,需要對編譯器進行設(shè)置,否則不會展開(因為debug模式下,編譯器默認不會對代碼進行優(yōu)化,以下給出vs2019的設(shè)置方式)

2.2內(nèi)聯(lián)函數(shù)的特性

  1. inline是一種以空間換時間的做法,如果編譯器將函數(shù)當(dāng)成內(nèi)聯(lián)函數(shù)處理,在編譯階段,會用函數(shù)體替換函數(shù)調(diào)用,缺陷:可能會使目標(biāo)文件變大,優(yōu)勢:少了調(diào)用開銷,提高程序運行效率。
  2. inline對于編譯器而言只是一個建議,不同編譯器關(guān)于inline實現(xiàn)機制可能不同,一般建議:將函數(shù)規(guī)模較小(即函數(shù)不是很長,具體沒有準(zhǔn)確的說法,取決于編譯器內(nèi)部實現(xiàn))、不是遞歸、且頻繁調(diào)用的函數(shù)采用inline修飾,否則編譯器會忽略inline特性。
    《C++prime》第五版關(guān)于inline的建議:
    內(nèi)聯(lián)函數(shù)只是向編譯器發(fā)送的一個請求,編譯器可以忽略這個請求
    一般來說,內(nèi)聯(lián)機制用于優(yōu)化規(guī)模較小,流程直接,頻繁調(diào)用的函數(shù),很多編譯器都不支持內(nèi)聯(lián)遞歸函數(shù),而且一個75行的函數(shù)也不太可能在調(diào)用點內(nèi)聯(lián)的展開。
  3. inline不建議聲明和定義分離,分離會導(dǎo)致鏈接錯誤。因為inline被展開,就沒有函數(shù)地址了,鏈接就會找不到
// 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),該符號在函數(shù) _main 中被引用

總結(jié)

我們這篇博客主要涉及C++語言中的引用和內(nèi)聯(lián)函數(shù),深入分析引用和內(nèi)聯(lián)函數(shù)中的很多細節(jié)問題,同時從底層匯編入手來分析引用和內(nèi)聯(lián)函數(shù)的底層原理~

到此這篇關(guān)于從底層入手搞定C++引用與內(nèi)聯(lián)函數(shù)的文章就介紹到這了,更多相關(guān)C++引用與內(nèi)聯(lián)函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于linux下C開發(fā)中的幾點技術(shù)經(jīng)驗總結(jié)

    基于linux下C開發(fā)中的幾點技術(shù)經(jīng)驗總結(jié)

    本篇文章是對linux下C開發(fā)中的幾點技術(shù)經(jīng)驗總結(jié)進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言實現(xiàn)通訊錄的方法(包括靜態(tài)版本和動態(tài)版本)

    C語言實現(xiàn)通訊錄的方法(包括靜態(tài)版本和動態(tài)版本)

    本文給大家分享C語言實現(xiàn)通訊錄的方法(包括靜態(tài)版本和動態(tài)版本),針對每種方法給大家介紹的非常詳細,需要的朋友參考下吧
    2021-09-09
  • 一篇文章帶你了解C語言浮點數(shù)之間的比較規(guī)則

    一篇文章帶你了解C語言浮點數(shù)之間的比較規(guī)則

    這篇文章主要介紹了魔性的float浮點數(shù)精度問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • 一文詳解matlab實現(xiàn)形態(tài)學(xué)圖像處理

    一文詳解matlab實現(xiàn)形態(tài)學(xué)圖像處理

    這篇文章主要為大家介紹了matlab實現(xiàn)形態(tài)學(xué)圖像處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • 利用C語言實現(xiàn)任務(wù)調(diào)度的示例代碼

    利用C語言實現(xiàn)任務(wù)調(diào)度的示例代碼

    這篇文章主要為大家詳細介紹了如何利用純C語言實現(xiàn)任務(wù)調(diào)度(可用于STM32、C51等單片機),文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2023-04-04
  • c語言小游戲程序之彈跳小球的實現(xiàn)代碼

    c語言小游戲程序之彈跳小球的實現(xiàn)代碼

    這篇文章主要介紹了c語言小游戲程序之彈跳小球的實現(xiàn)代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • C++單一職責(zé)原則示例代碼淺析

    C++單一職責(zé)原則示例代碼淺析

    我們在設(shè)計一個類時要學(xué)會發(fā)現(xiàn)職責(zé),并把那些職責(zé)相互分離,其實要去判斷是否應(yīng)該分離出一個類來并不難,前面說過,一個類應(yīng)該只有一個引起它變化的原因,如果你能想到其它的原因也能去改變這個類,那么這個類就具有多于1個的職責(zé),就應(yīng)該考慮類的職責(zé)分離
    2023-02-02
  • Qt實現(xiàn)俄羅斯方塊

    Qt實現(xiàn)俄羅斯方塊

    這篇文章主要為大家詳細介紹了Qt實現(xiàn)俄羅斯方塊,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 動態(tài)數(shù)組C++實現(xiàn)方法(分享)

    動態(tài)數(shù)組C++實現(xiàn)方法(分享)

    下面小編就為大家?guī)硪黄獎討B(tài)數(shù)組C++實現(xiàn)方法(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • C語言實現(xiàn)數(shù)組元素排序方法詳解

    C語言實現(xiàn)數(shù)組元素排序方法詳解

    這篇文章主要為大家介紹了C語言算法練習(xí)中數(shù)組元素排序的實現(xiàn)方法,文中的示例代碼講解詳細,對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2023-02-02

最新評論

开封县| 亚东县| 崇信县| 尉犁县| 崇文区| 乐平市| 岗巴县| 津市市| 望谟县| 南雄市| 浦城县| 锦州市| 玛曲县| 庆安县| 宜宾市| 孝义市| 红安县| 建湖县| 阳曲县| 莱阳市| 桐城市| 鄢陵县| 莒南县| 墨玉县| 清涧县| 屏山县| 荔波县| 松江区| 招远市| 胶南市| 中宁县| 龙泉市| 襄垣县| 高密市| 岳池县| 渑池县| 罗源县| 武安市| 繁昌县| 措勤县| 东乌珠穆沁旗|