国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解

這篇具有很好參考價(jià)值的文章主要介紹了【C++】C++入門(mén)必備知識(shí)詳細(xì)講解。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

首先我們先要知道,C++是在C的基礎(chǔ)之上,容納進(jìn)去了面向?qū)ο缶幊趟枷?,并增加了許多有用的庫(kù)。本章將會(huì)帶大家了解,C++是補(bǔ)充C語(yǔ)言語(yǔ)法的不足,以及C++是如何對(duì)C語(yǔ)言設(shè)計(jì)不合理的地方進(jìn)行優(yōu)化的。

一、命名空間

1. namespace

在C/C++中,變量、函數(shù)等等都是大量存在的,這些變量、函數(shù)和類(lèi)的名稱將都存在于全局作用域中,可能會(huì)導(dǎo)致很多沖突。使用命名空間的目的是對(duì)標(biāo)識(shí)符的名稱進(jìn)行本地化,以避免命名沖突,namespace 關(guān)鍵字的出現(xiàn)就是針對(duì)這種問(wèn)題的。

例如,我們想定義一個(gè)變量 sqrt ,直接定義在全局變量然后編譯是可以通過(guò)的,例如下圖:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
但是,我們知道 sqrt 其實(shí)是一個(gè)庫(kù)函數(shù),它包含在 math.h 的頭文件中,假設(shè)我們加上 math.h 的頭文件,還能編譯過(guò)嗎?答案是不能,因?yàn)樗鼈冎孛耍绻?math.h 的頭文件,編譯不會(huì)通過(guò),會(huì)報(bào)下圖中的錯(cuò)誤:
【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

那么有沒(méi)有好的解決方案呢,答案是有的,C++中就增加了 namespace 這樣的關(guān)鍵字解決這樣的問(wèn)題。例如我們可以將我們需要定義的變量放入 namespace 的命名空間中,然后在使用讓編譯器在指定的命名空間中尋找;如果不指定編譯器,編譯器優(yōu)先會(huì)在全局域中尋找變量;namespace 的使用:

		#include <stdio.h>
		#include <math.h>
		
		// 命名空間的名字
		namespace Young
		{
			int sqrt = 10;
		}
		
		int main()
		{
			printf("%d\n", Young::sqrt);
			return 0;
		}

上述代碼的使用就是讓編譯器在指定的命名空間 Young 中去尋找變量 sqrt 然后使用這個(gè)變量,這樣就不會(huì)與庫(kù)函數(shù)中的 sqrt 函數(shù)有命名沖突了;Young 是一個(gè)可以自己命名的命名空間的名字,可以取任意名字,不一定是 Young.

printf("%d\n", Young::sqrt);中,sqrt 前面的 :: 符號(hào),叫做域作用限定符,意思是讓編譯器使用域作用限定符前面的命名空間中定義的東西。

2. namespace 的使用場(chǎng)景

除了上面我們使用 namespace 在命名空間中定義變量外,還可以定義函數(shù)、結(jié)構(gòu)體等;除此之外,還可以嵌套使用。例如以下代碼:

		namespace Young
		{
			//變量
			int sqrt = 10;
		
			// 函數(shù)
			int Add(int a, int b)
			{
				return a + b;
			}
		
			// 結(jié)構(gòu)體
			struct ListNode
			{
				int data;
				struct ListNode* next;
			};
		
			// 嵌套使用 
			namespace Y
			{
				int a = 10;
			}
		
		}
		
		int main()
		{
			int ret = Young::Add(1, 2);
			printf("%d\n", ret);
		
			struct Young::ListNode node;
		
			printf("%d\n", Young::Y::a);
		
			return 0;
		}

上述代碼中主函數(shù)部分,結(jié)構(gòu)體中的域作用限定符是要在 ListNode 前使用,而不是在 struct 前使用;嵌套使用 namespace 是從右往左看,到指定的命名空間中去尋找;

雖然這種方法可以有效避免命名沖突問(wèn)題,但是每次用的時(shí)候都要在前面加上域作用限定符,是不是很麻煩呢?確實(shí)是,但是還有一種方法可以解決,將命名空間展開(kāi);以上面的命名空間為例,例如以下代碼:

		// 將命名空間展開(kāi)
		using namespace Young;
		using namespace Y;
		
		int main()
		{
			int ret = Add(1, 2);
			printf("%d\n", ret);
		
			struct ListNode node;
		
			printf("%d\n",a);
		
			return 0;
		}

上面的代碼就將 Young 和 Y 兩個(gè)命名空間中的內(nèi)容展開(kāi),就不用再使用域作用限定符了;除此之外,我們還可以展開(kāi)部分命名空間中的內(nèi)容,例如,我只展開(kāi) Add 函數(shù)出來(lái):

		// 展開(kāi)部分
		using Young::Add;
		
		int main()
		{
			int ret = Add(1, 2);
			printf("%d\n", ret);
		
			struct Young::ListNode node;
		
			printf("%d\n", Young::Y::a);
		
			return 0;
		}

以上就是展開(kāi)部分的命名空間,通常在做項(xiàng)目的時(shí)候,我們都不會(huì)將命名空間展開(kāi),因?yàn)檎归_(kāi)就會(huì)變得不安全;但是在平常我們?cè)趯?xiě)代碼練習(xí)的時(shí)候,可以將命名空間展開(kāi),更有利于我們練習(xí)。

二、了解 C++ 中的輸入和輸出

首先我們先要知道,C++中引入了不同于C語(yǔ)言的輸入和輸出,在C語(yǔ)言中我們使用 scanf 和 printf 作為輸入和輸出,但是在C++中了 cout 標(biāo)準(zhǔn)輸出對(duì)象(控制臺(tái))和 cin 標(biāo)準(zhǔn)輸入對(duì)象(鍵盤(pán));我們先看看它們的使用:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

我們可以了解到,上述代碼中的 cout 和 cin 分別叫做流插入運(yùn)算符流提取運(yùn)算符,關(guān)于這兩個(gè)更多的我們?cè)谝院蟮膶W(xué)習(xí)中再介紹;其中 cout 和 cin 必須包含< iostream >頭文件以及按命名空間使用方法使用 std ,其中 std 是C++標(biāo)準(zhǔn)庫(kù)的命名空間名,C++將標(biāo)準(zhǔn)庫(kù)的定義實(shí)現(xiàn)都放到這個(gè)命名空間中。所以我們可以展開(kāi) std 的命名空間:

		#include <iostream>
		using namespace std;
		
		int main()
		{
			int input;
			double d;
			// 自動(dòng)識(shí)別類(lèi)型
			cin >> input >> d;
		
			cout << input << endl << d << endl;
			return 0;
		}

除此之外,cin 和 cout 還可以自動(dòng)識(shí)別變量的類(lèi)型,如上述代碼,它的輸出如下圖:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

三、缺省參數(shù)

缺省參數(shù)是聲明或定義函數(shù)時(shí)為函數(shù)的參數(shù)指定一個(gè)缺省值。在調(diào)用該函數(shù)時(shí),如果沒(méi)有指定實(shí)參則采用該形參的缺省值,否則使用指定的實(shí)參。先看看缺省參數(shù)的使用:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
在上面的使用中,Add 函數(shù)就是用了缺省參數(shù),在 Add 函數(shù)定義中,它指定了 a = 100,b = 200,意思就是,當(dāng)調(diào)用 Add 函數(shù)時(shí),如果沒(méi)有參數(shù)傳進(jìn)來(lái),就使用它自己定義的變量;傳參時(shí),就使用指定的實(shí)參,如下圖:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
當(dāng)然也可以只傳一部分參數(shù),但是當(dāng)出現(xiàn)多個(gè)參數(shù)時(shí),參數(shù)必須從右往左依次來(lái)給出,不能間隔著給;例如:

		#include <iostream>
		using namespace std;
		
		int Add(int a = 100, int b = 200, int c = 300)
		{
			return a + b + c;
		}
		
		int main()
		{
			int a = 10, b = 20, c = 30;
		
			int ret = Add(a);
			cout << ret << endl;
			return 0;
		}

以上這段的代碼輸出結(jié)果就是 510 ,那么例如 int ret = Add(a,,c); 這種傳參是不允許的。

那么我們可以給缺省參數(shù)分類(lèi),像上面代碼中,Add()這種什么都不傳的就叫做全缺省參數(shù);像Add(a)或者Add(a,b)這種只傳一部分的就叫做半缺省參數(shù)。

最后,我們要注意缺省參數(shù)不能在函數(shù)聲明定義中同時(shí)出現(xiàn),如果在函數(shù)聲明和函數(shù)中同時(shí)出現(xiàn),我們只需要在聲明中給缺省值即可。

四、函數(shù)重載

1. 函數(shù)重載的概念

函數(shù)重載:是函數(shù)的一種特殊情況,C++允許在同一作用域中聲明幾個(gè)功能類(lèi)似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個(gè)數(shù) 或 類(lèi)型 或 類(lèi)型順序)不同,常用來(lái)處理實(shí)現(xiàn)功能類(lèi)似數(shù)據(jù)類(lèi)型不同的問(wèn)題。我們先看使用:

		#include <iostream>
		using namespace std;
		
		void Add(int a ,double b)
		{
			// 打印數(shù)據(jù)方便觀察
			cout << "void Add(int a ,double b)" << endl;
		}
		
		
		void Add(double a, int b)
		{
			// 打印數(shù)據(jù)方便觀察
			cout << "void Add(double a, int b)" << endl;
		}
		
		
		int main()
		{
		
			Add(3, 3.14);
			Add(3.14, 3);
			
			return 0;
		}

運(yùn)行的結(jié)果如下:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
以上代碼中,我們?cè)诤瘮?shù)中打印數(shù)據(jù),是為了說(shuō)明編譯器調(diào)用了這個(gè)函數(shù);我們定義了兩個(gè)同名的函數(shù),但是它們的參數(shù)類(lèi)型不一樣,而我們?cè)谑褂眠@兩個(gè)函數(shù)的時(shí)候,傳的參數(shù)也不一樣,所以它們會(huì)調(diào)用各自對(duì)應(yīng)的函數(shù);

2. C++支持函數(shù)重載的原理

C++支持函數(shù)重載的原理是因?yàn)镃++有自己的函數(shù)名修飾規(guī)則。
我們知道,.cpp文件或者.c文件在生成可執(zhí)行程序之前,要經(jīng)過(guò)預(yù)處理,編譯,匯編,鏈接的過(guò)程,具體回顧往期博客:預(yù)處理和程序環(huán)境;

其中,C語(yǔ)言在編譯過(guò)程中,符號(hào)匯總將所有.c文件的函數(shù)名匯總在一起,注意,是函數(shù)名,所以在C語(yǔ)言中,重名的函數(shù)名在編譯過(guò)程中會(huì)有沖突,編譯不通過(guò);

但是,在C++中的函數(shù)名修飾規(guī)則中,C++不是用函數(shù)名匯總在一起,而是有它自己的修飾規(guī)則,具體的修飾規(guī)則在不同的編譯器有不同的修飾規(guī)則,例如:

		void func(int i, double d)
		{}
		
		void func(double d, int i)
		{}

這兩個(gè)函數(shù),在 g++ 編譯器的函數(shù)修飾后變成【_Z+函數(shù)長(zhǎng)度+函數(shù)名+類(lèi)型首字母】,如圖:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
所以它們?cè)诰幾g匯總的時(shí)候是可以區(qū)分開(kāi)來(lái)的。

五、引用

1. 引用的概念

引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會(huì)為引用變量開(kāi)辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。先看一個(gè)簡(jiǎn)單的例子:

		#include <iostream>
		using namespace std;
		
		int main()
		{
			int a = 10;
			int& b = a;
			return 0;
		}

以上代碼中int& b = a;就是在定義引用類(lèi)型,b 就是 a 的別名,a 和 b 實(shí)際上都是指向同一個(gè)空間,a 的改變會(huì)影響 b ,b 的改變也會(huì)影響 a.

2. 引用特性

  1. 引用在定義時(shí)必須初始化

  2. 一個(gè)變量可以有多個(gè)引用

  3. 引用一旦引用一個(gè)實(shí)體,再不能引用其他實(shí)體

     	void Test()
     	{
     		int a = 10;
     		// int& ra;   // 該語(yǔ)句編譯時(shí)會(huì)出錯(cuò)
     		int& ra = a;
     		int& rra = a;
     	}
    

int& ra; 會(huì)編譯出錯(cuò)是因?yàn)樵诙x時(shí)沒(méi)有初始化;上述代碼中,rra 是 ra 的別名,也是 a 的別名,這三個(gè)變量用的都是同一個(gè)空間,它們之間的互相改變都會(huì)影響彼此。

3. 常引用

我們?cè)谑褂靡脮r(shí)要遵守一條規(guī)則,就是在引用的過(guò)程中,權(quán)限可以平移,權(quán)限也可以縮小,但是權(quán)限不能放大。例如:

		int main()
		{
			const int a = 0;
			// 權(quán)限的放大,不允許
			//int& b = a;
		
			// 不算權(quán)限的放大,因?yàn)檫@里是賦值拷貝,b修改不影響a
			//int b = a; 
		
			// 權(quán)限的平移,允許
			const int& c = a;
		
			// 權(quán)限的縮小,允許
			int x = 0;
			const int& y = x;
		
			return 0;
		}

上述代碼中,權(quán)限的放大是指,const int a = 0;const修飾的 a 變量具有常性,不可修改,是只讀,但是int& b = a;代表 b 的值可修改,并且 b 的值修改會(huì)影響 a ,b 是可讀可寫(xiě)的,但是 a 只有只讀,所以這里是權(quán)限的放大;但是int b = a; 不算權(quán)限的放大,因?yàn)檫@里是賦值拷貝,b 的修改不影響 a.

權(quán)限的平移是指,大家都具有一樣的權(quán)限,例如上述代碼中的const int& c = a;此處的 c 和 a 都被 const 修飾了,大家都具有常性,所以是權(quán)限的平移,是可以的。

權(quán)限的縮小在上述代碼中,int x = 0; const int& y = x;是指 x 是可讀可寫(xiě)的,但 y 被 const 修飾了,只有只讀,但是從可讀可寫(xiě)轉(zhuǎn)變成只讀是允許的,這種就叫做權(quán)限的縮小。

那么我們看一下以下的語(yǔ)句屬于什么呢?

		void test()
		{
			int i = 0;
			double& d = i;
		}

首先我們應(yīng)該了解清楚,如果是int i = 0; double d = i;也是可以的,因?yàn)樗鼈冎g會(huì)發(fā)生整型提升;那么我們要清楚,這個(gè)整型提升的過(guò)程中,會(huì)發(fā)生拷貝的過(guò)程,d 取的是 i 的臨時(shí)拷貝,如下圖,而這個(gè)臨時(shí)拷貝具有常性,不可被修改,所以這里是權(quán)限的放大,是不允許的。
【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
所以正確的語(yǔ)句應(yīng)該如下:

		void test()
		{
			int i = 0;
			const double& d = i;
		}

將 d 的屬性也變成不可修改,那么它們之間就是權(quán)限的平移關(guān)系了。

4. 引用的使用場(chǎng)景

(1)做參數(shù)(傳引用傳參)

我們常見(jiàn)的傳引用傳參就是交換函數(shù)了,寫(xiě)一個(gè)我們常用的交換函數(shù)如下:

		#include <iostream>
		using namespace std;
		
		void Swap(int* p1, int* p2)
		{
			int tmp = *p1;
			*p1 = *p2;
			*p2 = tmp;
		}
		
		int main()
		{
			int a = 10, b = 20;
		
			Swap(&a, &b);
			
			return 0;
		}

在這個(gè)交換函數(shù)中,我們需要傳 a 的地址和 b 的地址過(guò)去,才能改變 a 和 b 的值;在C++中,我們可以使用引用完成同樣的交換,代碼如下:

		void Swap(int& p1, int& p2)
		{
			int tmp = p1;
			p1 = p2;
			p2 = tmp;
		}
		
		int main()
		{
			int a = 10, b = 20;
		
			Swap(a, b);
		
			return 0;
		}

使用了引用后,代碼整體看起來(lái)就很舒服,不用像指針那樣傳地址和解引用;同時(shí)傳引用傳參還能提高傳參的效率,因?yàn)槊恳淮蝹髦坊蛘邆髦刀际且淮慰截悾總饕淮尉鸵嗫截愐淮?,效率很低;而引用則不需要拷貝,因?yàn)樾螀⑹菍?shí)參的別名,就不用進(jìn)行拷貝。

除此之外,傳引用傳參最舒服的地方還是在我們以前學(xué)過(guò)的單鏈表中,如往期博客 單鏈表 中,無(wú)論是頭插還是尾插等等操作,都需要傳二級(jí)指針才能改變鏈表的整體結(jié)構(gòu),而C++引入了引用之后,就不需要傳二級(jí)指針了,如下代碼:

		void SLTPushBack(SLTNode*& phead, SLTDateType x)
		{
		    // ...
		    if (phead == NULL)
		    {
		        phead = newnode;
		    }
		    else
		    {
		        //...
		    }
		}
		
		int main()
		{
		    SLTNode* plist = NULL;
		
		    SLTPushBack(plist, 1);
		    SLTPushBack(plist, 2);
		    SLTPushBack(plist, 3);
		
		    return 0;
		}

(2)做返回值(傳引用返回)

在使用傳引用返回時(shí)需要注意,不像傳引用傳參一樣,傳引用返回如果出了函數(shù)作用域?qū)ο筮€在的話才可以用,如果出了函數(shù)作用域?qū)ο蟛辉诰筒荒苡茫蝗缫韵麓a:

		int& func()
		{
			int n = 0;
			n = 10;
		
			return n;
		}
		
		int main()
		{
			int ret = func();
			
			return 0;
		}

在這段代碼中,函數(shù) func 內(nèi)定義了一個(gè)變量 n,但是它的生命周期只在這個(gè)函數(shù)內(nèi),出了函數(shù)作用域它的空間就會(huì)被銷(xiāo)毀,畫(huà)圖更好地理解:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
如上圖,func 銷(xiāo)毀后,n 隨之也會(huì)銷(xiāo)毀,將空間歸還給操作系統(tǒng),但是在 main 函數(shù)中,ret 實(shí)際上是相當(dāng)于訪問(wèn)已經(jīng)銷(xiāo)毀的 n ,這嚴(yán)格來(lái)說(shuō)相當(dāng)于野指針問(wèn)題了,也就是越界訪問(wèn)。

但是在不同的編譯器中,得出的結(jié)果卻不一樣,在 vs2019 中,是可以得到 n 的值,如下圖:
【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

而在 gcc/g++ 的編譯器中,卻報(bào)錯(cuò)了,如下圖:
【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
原因是因?yàn)椋@取決于棧幀銷(xiāo)毀之后,編譯器是否會(huì)對(duì)已經(jīng)銷(xiāo)毀的空間初始化,如果對(duì)已經(jīng)銷(xiāo)毀的空間進(jìn)行初始化,而繼續(xù)對(duì)它進(jìn)行訪問(wèn),就是越界,像 gcc/g++ 這樣的編譯器,很明顯在空間回收時(shí)會(huì)對(duì)空間進(jìn)行初始化,所以造成越界;而 vs2019 則沒(méi)有嚴(yán)格的檢查。

拓展:那如果將代碼改成如下,還能編譯通過(guò)嗎?

		int& func()
		{
			int n = 0;
			n = 10;
		
			return n;
		}
		
		int main()
		{
			int& ret = func();
			cout << ret << endl;
			cout << ret << endl;
		
			return 0;
		
		}

這里將 ret 的接收改成了引用,也就是說(shuō),ret 是返回的 n 的別名,我們看執(zhí)行結(jié)果:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
第二次執(zhí)行是隨機(jī)值,為什么呢?原因是因?yàn)?ret 是 n 的別名,它們公用同一個(gè)空間,在執(zhí)行 cout 語(yǔ)句時(shí),也會(huì)發(fā)生一系列函數(shù)棧幀的創(chuàng)建,所以新的空間會(huì)覆蓋之前的 func 所在的空間,也就是說(shuō),n 的空間被覆蓋了,也就是 ret 的空間被覆蓋了,所以 n 的值也就變成了隨機(jī)值;第一次是 10 的原因是原來(lái)的空間并沒(méi)有被覆蓋。

所以就引入了另一個(gè)話題,如果 n 的空間沒(méi)有被覆蓋,它是不是還是 10 呢?那么我們將代碼修改成以下代碼:

		int& func()
		{
			int a[1000];
			int n = 0;
			n = 10;
		
			return n;
		}
		
		int main()
		{
			int& ret = func();
			
			cout << ret << endl;
			cout << ret << endl;
		
			return 0;
		}

在 func 函數(shù)內(nèi),我們?cè)黾恿艘粋€(gè)長(zhǎng)度為 1000 的數(shù)組,我們先看運(yùn)行結(jié)果:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

這個(gè)時(shí)候又變成了 10 ,這是因?yàn)楹瘮?shù)的棧幀中空間是向下創(chuàng)建的,所以在 func 函數(shù)內(nèi),先創(chuàng)建 1000 個(gè)空間,然后再為 n 創(chuàng)建空間,n 這個(gè)時(shí)候的位置是處于下方的;如果 func 銷(xiāo)毀后,如果有新的空間覆蓋,這要取決于這個(gè)空間是否比原來(lái) func 的空間要大,如果這個(gè)空間很大,覆蓋了 n ,那么 n 就會(huì)變成隨機(jī)值,否則,n 還是原來(lái)的值。

那么傳引用返回有什么應(yīng)用場(chǎng)景呢?我們常見(jiàn)的傳引用返回可以用作修改返回對(duì)象,例如在單鏈表中,查找函數(shù)和修改函數(shù)可以合并在一起寫(xiě),使用傳引用返回,這樣就既可以查找到想要查找的數(shù)據(jù),又能修改想要修改的值。例如以下代碼:

		int& SLFindOrModify(struct SeqList& ps, int i)
		{
			assert(i < ps.size);
			// ...
			return (ps.a[i]);
		}
		
		int main()
		{
			// 定義對(duì)象
			struct SeqList s;
			
			// 查找 10 這個(gè)數(shù)據(jù),并將它修改成 20
			SLFindOrModify(s, 10) = 20;
		
			return 0;
		}

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

現(xiàn)在我們都學(xué)過(guò)指針和引用了,我們可以發(fā)現(xiàn),其實(shí)引用和指針很相似,在很多用法上指針可以代替引用,引用也可以代替指針,那么它們之間又有什么區(qū)別呢?我們一一分析:

引用和指針的不同點(diǎn):

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

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

1. #define定義宏

我們以前學(xué)過(guò) #define定義宏,如往期博客 #define定義宏 中,宏給我們帶來(lái)很多好處,如針對(duì)頻繁調(diào)用的小函數(shù),不需要建立棧幀,提高了效率;如以下代碼:

		#define ADD(a,b) ((a)+(b))
		
		int main()
		{
			int ret = ADD(10, 20);
		
			cout << ret << endl;
			return 0;
		}

以上的宏定義了兩個(gè)數(shù)的相加,注意,這里宏定義的((a)+(b))不能寫(xiě)成(a+b),因?yàn)榭紤]到運(yùn)算符優(yōu)先級(jí)問(wèn)題,如ADD(1 | 2 + 1 & 2)這種表達(dá)式,加號(hào)優(yōu)先級(jí)更高,會(huì)先執(zhí)行加的操作,再執(zhí)行 | 和 & ,并不是我們想要的結(jié)果。

上面的宏定義在預(yù)處理階段是直接展開(kāi)替換,所以沒(méi)有建立棧幀,很好地提高了效率。

但是宏給我們帶來(lái)好處的同時(shí),必然會(huì)帶來(lái)不便,如使用宏定義會(huì)容易出錯(cuò),就如上面兩數(shù)相加的宏,少一個(gè)括號(hào)都不行,所以宏的語(yǔ)法坑很多。

最后總結(jié)一下宏的優(yōu)缺點(diǎn):

優(yōu)點(diǎn):

  1. 沒(méi)有類(lèi)型的嚴(yán)格限制。
  2. 沒(méi)有函數(shù)棧幀的建立,提高效率。

缺點(diǎn):

  1. 不方便調(diào)試宏。(因?yàn)轭A(yù)編譯階段進(jìn)行了替換)
  2. 導(dǎo)致代碼可讀性差。
  3. 沒(méi)有類(lèi)型安全的檢查 。
  4. 容易出錯(cuò),語(yǔ)法坑多。

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

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

例如以下的兩數(shù)相加的內(nèi)聯(lián)函數(shù):

		inline int Add(int a, int b)
		{
			return a + b;
		}
		
		int main()
		{
			int ret = Add(10, 20);
		
			cout << ret << endl;
			return 0;
		}

以上代碼中,兩數(shù)相加的內(nèi)聯(lián)函數(shù)既沒(méi)有建立函數(shù)棧幀,性能有很好的體現(xiàn),也沒(méi)有因?yàn)檫\(yùn)算符問(wèn)題需要添加很多括號(hào),所以內(nèi)聯(lián)函數(shù)是綜合了宏和函數(shù)的優(yōu)缺點(diǎn)來(lái)設(shè)計(jì)的。

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

(1) inline是一種以空間換時(shí)間的做法,如果編譯器將函數(shù)當(dāng)成內(nèi)聯(lián)函數(shù)處理,在編譯階段,會(huì)用函數(shù)體替換函數(shù)調(diào)用,缺陷:可能會(huì)使目標(biāo)文件變大,優(yōu)勢(shì):少了調(diào)用開(kāi)銷(xiāo),提高程序運(yùn)行效率。

(2) inline對(duì)于編譯器而言只是一個(gè)建議,不同編譯器關(guān)于inline實(shí)現(xiàn)機(jī)制可能不同,一般建議:將函數(shù)規(guī)模較小(即函數(shù)不是很長(zhǎng),具體沒(méi)有準(zhǔn)確的說(shuō)法,取決于編譯器內(nèi)部實(shí)現(xiàn))、不是遞歸、且頻繁調(diào)用的函數(shù)采用inline修飾,否則編譯器會(huì)忽略inline特性。

也就是說(shuō),假設(shè)你使用了 inline,編譯器也不一定會(huì)視這個(gè)函數(shù)為內(nèi)聯(lián)函數(shù),因?yàn)槿绻@個(gè)函數(shù)的規(guī)模很大,代碼量大,會(huì)造成代碼膨脹,所以綜合性能方面考慮,我們?nèi)绻褂脙?nèi)聯(lián)函數(shù),盡量要簡(jiǎn)化代碼。

(3) inline 不建議聲明和定義分離,分離會(huì)導(dǎo)致鏈接錯(cuò)誤。因?yàn)?inline 被展開(kāi),就沒(méi)有函數(shù)地址了,鏈接就會(huì)找不到。

例如我定義了一個(gè) Test.h 的頭文件,里面包含 Add 函數(shù)的聲明:

		inline int Add(int a, int b);

再定義一個(gè) Test.cpp 文件,里面包含 Add 函數(shù)的實(shí)現(xiàn):

		#include "Test.h"
		int Add(int a, int b)
		{
			return a + b;
		}

然后在 main.cpp 函數(shù)中調(diào)用 Add 函數(shù):

		#include "Test.h"

		int main()
		{
			int ret = Add(10, 20);
		
			cout << ret << endl;
			return 0;
		}

最后編譯出錯(cuò)了,如下圖:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
這是因?yàn)槭裁茨??原因是因?yàn)轭^文件 #include "Test.h" 會(huì)在預(yù)處理階段在 main.cpp 文件中展開(kāi),展開(kāi)之后會(huì)有函數(shù) Add 的聲明,而 Add 函數(shù)前加了內(nèi)聯(lián) inline,編譯器會(huì)認(rèn)為它就是一個(gè)內(nèi)聯(lián)函數(shù),認(rèn)為它就會(huì)直接展開(kāi),所以在編譯階段沒(méi)有給它一個(gè)有效的地址,也就沒(méi)有進(jìn)入符號(hào)表;而在 main 函數(shù)中調(diào)用了 Add 函數(shù),它在符號(hào)表中并沒(méi)有找到自己對(duì)應(yīng)函數(shù)的地址,所以會(huì)出現(xiàn)鏈接錯(cuò)誤。

七、auto關(guān)鍵字

在 C++11 中,auto 的含義是,auto 聲明的變量必須由編譯器在編譯時(shí)期推導(dǎo)而得。也就是說(shuō),auto 是一個(gè)根據(jù)變量自動(dòng)推導(dǎo)類(lèi)型的關(guān)鍵字。

例如:
【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

八、基于范圍的for循環(huán)(C++11)

當(dāng)我們需要遍歷一個(gè)數(shù)組時(shí),通常使用以下方式:

		int main()
		{
			int arr[] = { 1,2,3,4,5,6,7,8 };
		
			for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
			{
				cout << arr[i] << " ";
			}
		
			return 0;
		}

對(duì)于一個(gè)有范圍的集合而言,由程序員來(lái)說(shuō)明循環(huán)的范圍是多余的,有時(shí)候還會(huì)容易犯錯(cuò)誤。因此 C++11 中引入了基于范圍的 for 循環(huán)。for 循環(huán)后的括號(hào)由冒號(hào)“ :”分為兩部分:第一部分是范圍內(nèi)用于迭代的變量,第二部分則表示被迭代的范圍。使用范圍 for 我們可以結(jié)合上面所學(xué)的 auto 關(guān)鍵字結(jié)合使用,例如以下代碼:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
如果我們需要改變數(shù)組中的值,是否像以下代碼那樣使用呢?

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

很明顯,答案是不可以的,因?yàn)?e 只是數(shù)組中的數(shù)據(jù)的臨時(shí)拷貝,改變臨時(shí)拷貝的值不影響數(shù)組中原來(lái)的值,所以我們要加上引用:

		int main()
		{
			int arr[] = { 1,2,3,4,5,6,7,8 };
		
			for (auto& e : arr)
			{
				e *= 2;
			}
		
			for (auto e : arr)
			{
				cout << e << " ";
			}
			return 0;
		}

加上引用后,e 就是數(shù)組中的數(shù)據(jù)的別名,改變 e 也就是改變數(shù)組中的內(nèi)容。

九、指針空值 nullptr

在早期設(shè)計(jì) NULL 空指針時(shí),NULL 實(shí)際上就是 0,所以導(dǎo)致有些地方使用 NULL 會(huì)造成不明確的函數(shù)調(diào)用,例如:

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言
在以上代碼中,func 構(gòu)成函數(shù)重載,我們期望的 NULL 是調(diào)用 void func(int*) 函數(shù),但是它卻調(diào)用了另外一個(gè),所以這造成了不明確的函數(shù)調(diào)用。

所以在 C++11 中,引入了 nullptr,它的類(lèi)型是無(wú)類(lèi)型指針(void*),這很好地避免了以上的情況,例如下圖,nullptr 是調(diào)用了具有指針類(lèi)型的函數(shù):

【C++】C++入門(mén)必備知識(shí)詳細(xì)講解,c++,c語(yǔ)言,jvm,開(kāi)發(fā)語(yǔ)言

最后,C++ 入門(mén)的全部?jī)?nèi)容已經(jīng)全部分享完啦,感覺(jué)對(duì)自己有幫助的小伙伴趕緊點(diǎn)贊收藏吧~感謝支持!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-588029.html

到了這里,關(guān)于【C++】C++入門(mén)必備知識(shí)詳細(xì)講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C語(yǔ)言】指針的基本知識(shí)詳細(xì)講解(指針數(shù)組、數(shù)組指針、函數(shù)指針....

    【C語(yǔ)言】指針的基本知識(shí)詳細(xì)講解(指針數(shù)組、數(shù)組指針、函數(shù)指針....

    接著上次的函數(shù)的基本知識(shí),今天我們來(lái)講一講??指針 目錄 一、指針的概念 二、指針變量 三、野指針 四、字符指針 五、指針與數(shù)組 六、指針數(shù)組 七、數(shù)組指針 ?八、指針與函數(shù) 總結(jié) 一、指針的概念 1.1、變量和地址 所謂指針,也就是內(nèi)存的地址;所謂指針變量,也就是

    2023年04月08日
    瀏覽(23)
  • 【C++初階】一、入門(mén)知識(shí)講解(C++關(guān)鍵字、命名空間、C++輸入&輸出、缺省參數(shù)、函數(shù)重載)

    【C++初階】一、入門(mén)知識(shí)講解(C++關(guān)鍵字、命名空間、C++輸入&輸出、缺省參數(shù)、函數(shù)重載)

    ========================================================================= 相關(guān)代碼gitee自取 : C語(yǔ)言學(xué)習(xí)日記: 加油努力 (gitee.com) ?========================================================================= 接上期 : 【數(shù)據(jù)結(jié)構(gòu)初階】十一、歸并排序(比較排序)的講解和實(shí)現(xiàn) (遞歸版本 + 非遞歸版本 -- C語(yǔ)言實(shí)

    2024年02月05日
    瀏覽(30)
  • 詳解爬蟲(chóng)基本知識(shí)及入門(mén)案列(爬取豆瓣電影《熱辣滾燙》的短評(píng) 詳細(xì)講解代碼實(shí)現(xiàn))

    詳解爬蟲(chóng)基本知識(shí)及入門(mén)案列(爬取豆瓣電影《熱辣滾燙》的短評(píng) 詳細(xì)講解代碼實(shí)現(xiàn))

    目錄 前言什么是爬蟲(chóng)? 爬蟲(chóng)與反爬蟲(chóng)基礎(chǔ)知識(shí) 一、網(wǎng)頁(yè)基礎(chǔ)知識(shí) ?二、網(wǎng)絡(luò)傳輸協(xié)議 HTTP(HyperText Transfer Protocol)和HTTPS(HTTP Secure)請(qǐng)求過(guò)程的原理? 三、Session和Cookies Session Cookies Session與Cookies的區(qū)別與聯(lián)系 ?四、Web服務(wù)器Nginx 五、代理IP 1、代理IP的原理 2. 分類(lèi) 3. 獲取途

    2024年04月29日
    瀏覽(90)
  • JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的必備知識(shí):Java程序員不容錯(cuò)過(guò)

    JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的必備知識(shí):Java程序員不容錯(cuò)過(guò)

    JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)是Java虛擬機(jī)在執(zhí)行Java程序時(shí)所使用的內(nèi)存區(qū)域。這些區(qū)域包括了以下幾個(gè)部分: 程序計(jì)數(shù)器(Program Counter Register):程序計(jì)數(shù)器是一塊較小的內(nèi)存區(qū)域,它可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。每一個(gè)線程都有自己獨(dú)立的程序計(jì)數(shù)器,用于記錄

    2023年04月15日
    瀏覽(23)
  • 從C語(yǔ)言到C++:C++入門(mén)知識(shí)(2)

    從C語(yǔ)言到C++:C++入門(mén)知識(shí)(2)

    朋友們、伙計(jì)們,我們又見(jiàn)面了,本期來(lái)給大家解讀一下有關(guān)C++的基礎(chǔ)知識(shí)點(diǎn),如果看完之后對(duì)你有一定的啟發(fā),那么請(qǐng)留下你的三連,祝大家心想事成! C 語(yǔ) 言 專 欄: C語(yǔ)言:從入門(mén)到精通 數(shù)據(jù)結(jié)構(gòu)專欄: 數(shù)據(jù)結(jié)構(gòu) 個(gè)? 人? 主? 頁(yè)?: stackY、 目錄 前言: 1. 函數(shù)重載

    2024年02月08日
    瀏覽(57)
  • 從C語(yǔ)言到C++:C++入門(mén)知識(shí)(1)

    從C語(yǔ)言到C++:C++入門(mén)知識(shí)(1)

    朋友們、伙計(jì)們,我們又見(jiàn)面了,本期來(lái)給大家解讀一下有關(guān)C++語(yǔ)言的相關(guān)知識(shí)點(diǎn),如果看完之后對(duì)你有一定的啟發(fā),那么請(qǐng)留下你的三連,祝大家心想事成! C 語(yǔ) 言 專 欄: C語(yǔ)言:從入門(mén)到精通 數(shù)據(jù)結(jié)構(gòu)專欄: 數(shù)據(jù)結(jié)構(gòu) 個(gè)? 人? 主? 頁(yè)?: stackY、 ? 目錄 前言: 1. 什么

    2024年02月07日
    瀏覽(28)
  • C++入門(mén)知識(shí)點(diǎn)——解決C語(yǔ)言不足

    C++入門(mén)知識(shí)點(diǎn)——解決C語(yǔ)言不足

    ????????????????????????Take your time ! ???????????????????????? ??個(gè)人主頁(yè):??????大魔王?????? ??所屬專欄:??魔王的修煉之路–C++?? 如果你覺(jué)得這篇文章對(duì)你有幫助,請(qǐng)?jiān)谖恼陆Y(jié)尾處留下你的 點(diǎn)贊 ??和 關(guān)注 ??,支持一下博主

    2024年02月12日
    瀏覽(22)
  • 【C++初階】二、入門(mén)知識(shí)講解(引用、內(nèi)聯(lián)函數(shù)、auto關(guān)鍵字、基于范圍的for循環(huán)、指針空值nullptr)

    【C++初階】二、入門(mén)知識(shí)講解(引用、內(nèi)聯(lián)函數(shù)、auto關(guān)鍵字、基于范圍的for循環(huán)、指針空值nullptr)

    ========================================================================= 相關(guān)代碼gitee自取 : C語(yǔ)言學(xué)習(xí)日記: 加油努力 (gitee.com) ?========================================================================= 接上期 : 【C++初階】一、入門(mén)知識(shí)講解 (C++、命名空間、C++輸入輸出、缺省參數(shù)、函數(shù)重載)-

    2024年02月04日
    瀏覽(97)
  • jvm中堆與棧的區(qū)別詳細(xì)講解

    在Java虛擬機(jī)(JVM)中,堆(Heap)和棧(Stack)是兩個(gè)重要的內(nèi)存區(qū)域,它們有著不同的特點(diǎn)和用途。 堆(Heap) ● 用途 :堆是Java中用于存儲(chǔ)對(duì)象的內(nèi)存區(qū)域。所有通過(guò)new創(chuàng)建的對(duì)象都會(huì)被分配到堆上。 ● 特點(diǎn) : ? 堆是一個(gè)大的內(nèi)存池,用于存儲(chǔ)所有的Java對(duì)象,包

    2024年04月13日
    瀏覽(18)
  • 深入理解JVM——垃圾回收與內(nèi)存分配機(jī)制詳細(xì)講解

    深入理解JVM——垃圾回收與內(nèi)存分配機(jī)制詳細(xì)講解

    所謂垃圾回收,也就是要回收已經(jīng)“死了”的對(duì)象。 那我們?nèi)绾闻袛嗄男?duì)象“存活”,哪些已經(jīng)“死去”呢? 給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器就加一;當(dāng)引用失效時(shí),計(jì)數(shù)器就減1;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。 但是

    2024年02月12日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包