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

帶你了解C++初階之引用

 更新時間:2022年01月15日 16:45:54   作者:跳動的bit  
這篇文章主要為大家介紹了C++初階之引用,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

一、 引用概念

引用不是新定義一個變量,而是給已存在變量取了一個別名,語法理解上程序不會為引用變量開辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間

比如:李逵,在家稱為"鐵牛",江湖上人稱"黑旋風(fēng)"

在這里插入圖片描述

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

int main()
{
	//有一塊空間a,后面給a取了三個別名b、c、d
	int a = 10;
	int& b = a;
	int& c = a;
	int& d = b;
	//char& d = a;//err,引用類型和引用實體不是同類型(這里有爭議————char a = b[int類型],留個懸念,下面會解答)
	//會被修改
	c = 20;
	d = 30;
	return 0;
}

注意

  • 引用類型必須和引用實體是同種類型
  • 注意區(qū)分 ‘&’ 取地址符號

二、 引用特性

  • 引用在定義時必須初始化
  • 一個變量可以有多個引用
  • 引用一旦引用一個實體,再不能引用其他實體
int main()
{
	//int& e;//err
	int a = 10;
	int& b = a;
	//這里指的是把c的值賦值于b
	int c = 20;
	b = c;
	return 0;
}

三、 常引用

void TestConstRef()
{
	const int a = 10;
	//int& ra = a; //該語句編譯時會出錯,a為常量;由const int到int
	const int& ra = a;//ok
	int b = 20;
	const int& c = b; //ok,由int到const int
	//b可以改,c只能讀不能寫
	b = 30;
	//c = 30;//err
	//b、c分別起的別名的權(quán)限可以是不變或縮小
	int& d = b;//ok
	//int& e = c//err
	const int& e = c;//ok
	//int& f = 10; // 該語句編譯時會出錯,b為常量
	const int& g = 10;//ok
	int h = 10;
	double i = h;//ok
	//double& j = h;//err
	const double& j = h;//ok
	//?為啥h能賦值給i了(隱式類型轉(zhuǎn)換),而給h起一個double類型的別名卻不行————如果是僅僅是類型的問題那為啥加上const就行了?
	//double i = h;并不是直接把h給i,而是在它們中間產(chǎn)生了一個臨時變量(double類型、常量),并利用這個臨時變量賦值
	//也就是說const double& j = h;就意味著j不是直接變成h的別名,而是變成臨時變量(doublde類型)的別名,但是這個臨時變量是一個常量,這也解釋了為啥需要加上const
}

小結(jié)

1.我能否滿足你變成別名的條件:可以不變或者縮小你讀寫的權(quán)限 (const int -> const int 或 int -> const int),而不能放大你讀寫的權(quán)限 (const int -> int)

2.別名的意義可以改變,并不是每個別名都跟原名有一樣的權(quán)限

3.不能給類型不同的變量起別名的真正原因不是類型不同,而是隱式類型轉(zhuǎn)換后具有常性了

 常引用的意義 (舉例棧)

typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;
void InitStack(ST& s)//傳引用是為了形參的改變影響實參
{//...}
void PrintStack(const ST& s)//1.傳引用是為了減少拷貝 2. 同時保護實參不會被修改
{//...}
void Test(const int& n)//即可以接收變量,也可以接收常量
{//...}
int main()
{
	ST st;
	InitStack(st);
	//...
	PrintStack(st);
	int i = 10;
	Test(i);
	Test(20);
	return 0;
}

小結(jié)

1.函數(shù)傳參如果想減少拷貝使用引用傳參,如果函數(shù)中不改變這個參數(shù)最好使用 const 引用傳參

2.const 引用的好處是保護實參,避免被誤改,且它可以傳普通對象也可以傳 const 對象

四、 使用場景

1、做參數(shù) 

void Swap1(int* p1, int* p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
void Swap2(int& rx, int& ry)
{
	int temp = rx;
	rx = ry;
	ry = temp;
}
int main()
{
	int x = 3, y = 5;
	Swap1(&x, &y);//C傳參
	Swap2(x, y);//C++傳參
	return 0;
}

在 C++ 中形參變量的改變,要影響實參,可以用指針或者引用解決

意義:指針實現(xiàn)單鏈表尾插 || 引用實現(xiàn)單鏈表尾插

指針

在這里插入圖片描述

引用

void SListPushBack(SLTNode*& phead, int x)
{
	//這里phead的改變就是plist的改變
}
void TestSList2()
{
	SLTNode* plist = NULL;
	SListPushBack(plist, 1);
	SListPushBack(plist, 2);
}

有些書上喜歡這樣寫 (不推薦)

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode, *PSLTNode;
void SListPushBack(PSLTNode& phead, int x)
{
	//...
}

2、做返回值 

2.1、傳值返回

//傳值返回
int Add(int a, int b)
{
	int c = a + b;
	return c;//需要拷貝
}
int main()
{
	int ret = Add(1, 2);//ok, 3
	Add(3, 4);
	cout << "Add(1, 2) is :"<< ret <<endl;
	return 0;
}

Add 函數(shù)里的 return c; —— 傳值返回,臨時變量作返回值。如果比較小,通常是寄存器;如果比較大,會在 main 函數(shù)里開辟一塊臨時空間

怎么證明呢

int Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	//int& ret = Add(1, 2);//err
	const int& ret = Add(1, 2);//ok, 3
	Add(3, 4);
	cout << "Add(1, 2) is :"<< ret <<endl;
	return 0;
}

從上面就可以驗證 Add 函數(shù)的返回值是先存儲在臨時空間里的

2.2、傳引用返回

//傳引用返回
int& Add(int a, int b)
{
	int c = a + b;
	return c;//不需要拷貝
}
int main()
{
	int ret = Add(1, 2);//err, 3
	Add(3, 4);
	cout << "Add(1, 2) is :"<< ret <<endl;
	return 0;
}

結(jié)果是不確定的,因為 Add 函數(shù)的返回值是 c 的別名,所以在賦給 ret 前,c 的值到底是 3 還是隨機值,跟平臺有關(guān)系 (具體是平臺銷毀棧幀時是否會清理棧幀空間),所以這里的這種寫法本身就是越界的 (越界抽查不一定報錯)、錯誤的

發(fā)現(xiàn)這樣也能跑,但詭異的是為啥 ret 是 7

//傳引用返回
int& Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = Add(1, 2);//err, 7
	Add(3, 4);
	cout << "Add(1, 2) is :"<< ret <<endl;
	return 0;
}

在上面我們在 VS 下運行,可以得出編譯器并沒有清理棧幀,那么這里進一步驗證引用返回的危害

雖然能正常運行,但是它是有問題的

在這里插入圖片描述

小結(jié)引用做返回值

1.出了 TEST 函數(shù)的作用域,ret 變量會銷毀,就不能引用返回

2. 出了 TEST 函數(shù)的作用域,ret 變量不會銷毀,就可以引用返回

3.引用返回的價值是減少拷貝

觀察并剖析以下代碼

int main()int main()
{
	int x = 3, y = 5;
	int* p1 = &x;
	int* p2 = &y;
	int*& p3 = p1;
	*p3 = 10;
	p3 = p2;
	return 0;
}

在這里插入圖片描述

五、函數(shù)參數(shù)及返回值 —— 傳值、傳引用效率比較

#include <time.h>#include<iostream>using namespace std;struct A { int a[10000]; };A a;void TestFunc1(A a) {}void TestFunc2(A& a) {}A TestFunc3() { return a; }A& TestFunc4() { return 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;}void TestReturnByRefOrValue(){// 以值作為函數(shù)的返回值類型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc3();size_t end1 = clock();// 以引用作為函數(shù)的返回值類型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc4();size_t end2 = clock();// 計算兩個函數(shù)運算完成之后的時間cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;}int main(){//傳值、傳引用效率比較TestRefAndValue();cout << "----------cut----------" << endl;//值和引用作為返回值類型的性能比較TestReturnByRefOrValue();return 0;}#include <time.h>
#include<iostream>
using namespace std;
struct A { int a[10000]; };
A a;
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
A TestFunc3() { return a; }
A& TestFunc4() { return 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;
}
void TestReturnByRefOrValue()
{
	// 以值作為函數(shù)的返回值類型
	size_t begin1 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc3();
	size_t end1 = clock();
	// 以引用作為函數(shù)的返回值類型
	size_t begin2 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc4();
	size_t end2 = clock();
	// 計算兩個函數(shù)運算完成之后的時間
	cout << "TestFunc1 time:" << end1 - begin1 << endl;
	cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
	//傳值、傳引用效率比較
	TestRefAndValue();
	cout << "----------cut----------" << endl;
	//值和引用作為返回值類型的性能比較
	TestReturnByRefOrValue();
	return 0;
}

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

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

1.語法概念

引用就是一個別名,沒有獨立空間,和其引用實體共用同一塊空間

指針變量是開辟一塊空間,存儲變量的地址

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

2.底層實現(xiàn) 

引用和指針是一樣的,因為引用是按照指針方式來實現(xiàn)的

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

這里我們對比一下 VS 下引用和指針的匯編代碼可以看出來他倆是同根同源

在這里插入圖片描述

引用和指針的不同點:

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

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

3 、沒有 NULL 引用,但有 NULL 指針

4、在 sizeof 中含義不同:引用結(jié)果為引用類型的大小,與類型有關(guān);但指針始終是地址空間所占字節(jié)個數(shù) (32 位平臺下占 4 個字節(jié),64 位平臺下占 8 個字節(jié)),與類型無關(guān)

5、引用自加即引用的實體增加 1,與類型無關(guān),指針自加即指針向后偏移一個類型的大小,與類型有關(guān)

6、有多級指針,但是沒有多級引用

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

8、引用比指針使用起來相對更安全,指針容易出現(xiàn)野指針、空指針等非法訪問問題

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • MFC中Radio Button的用法詳解

    MFC中Radio Button的用法詳解

    這篇文章主要介紹了MFC中Radio Button的用法,需要的朋友可以參考下
    2014-07-07
  • 詳談C語言指針

    詳談C語言指針

    這篇文章主要介紹了C語言的指針,介紹了其相關(guān)概念,然后分享了幾種用法,具有一定參考價值。需要的朋友可以了解下
    2021-10-10
  • C++特殊類設(shè)計概念與示例講解

    C++特殊類設(shè)計概念與示例講解

    本文介紹C++中三種特殊類設(shè)計模式:單例模式、工廠模式和代理模式。通過詳細(xì)講解每種設(shè)計模式的實現(xiàn)原理和應(yīng)用場景,幫助讀者理解和掌握這些常用的面向?qū)ο笤O(shè)計模式,并提供示例代碼和技巧,便于實際應(yīng)用
    2023-04-04
  • C++實現(xiàn)掃雷游戲(控制臺不閃屏版)

    C++實現(xiàn)掃雷游戲(控制臺不閃屏版)

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)掃雷游戲,控制臺不閃屏版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++中const的實現(xiàn)機制深入分析

    C++中const的實現(xiàn)機制深入分析

    C語言以及C++語言中的const究竟表示什么?其具體的實現(xiàn)機制又是如何實現(xiàn)的呢?本文將對這兩個問題進行一些分析,需要了解的朋友可以參考下
    2012-12-12
  • 用代碼和UML圖化解設(shè)計模式之橋接模式的深入分析

    用代碼和UML圖化解設(shè)計模式之橋接模式的深入分析

    本篇文章是對橋接模式進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言初識動態(tài)內(nèi)存管理malloc calloc realloc free函數(shù)

    C語言初識動態(tài)內(nèi)存管理malloc calloc realloc free函數(shù)

    動態(tài)內(nèi)存是相對靜態(tài)內(nèi)存而言的。所謂動態(tài)和靜態(tài)就是指內(nèi)存的分配方式。動態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存
    2022-03-03
  • 約瑟夫經(jīng)典問題擴展成雙向約瑟夫問題

    約瑟夫經(jīng)典問題擴展成雙向約瑟夫問題

    今天小編就為大家分享一篇關(guān)于約瑟夫經(jīng)典問題擴展成雙向約瑟夫問題,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • C語言中計算函數(shù)執(zhí)行時間的三種方式

    C語言中計算函數(shù)執(zhí)行時間的三種方式

    本文主要介紹了C語言中計算函數(shù)執(zhí)行時間的三種方式,主要包括clock(),timeb和time,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • 從頭學(xué)習(xí)C語言之指針和數(shù)組

    從頭學(xué)習(xí)C語言之指針和數(shù)組

    這篇文章主要為大家詳細(xì)介紹了C語言之指針和數(shù)組,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01

最新評論

房产| 建德市| 青浦区| 宁城县| 新竹市| 宁国市| 西峡县| 保靖县| 嵊泗县| 容城县| 永修县| 松潘县| 衡阳县| 都江堰市| 兴和县| 元谋县| 家居| 商南县| 临安市| 宣武区| 突泉县| 洛隆县| 黔西县| 恩施市| 恩施市| 新巴尔虎右旗| 大田县| 含山县| 合作市| 桃江县| 张家界市| 理塘县| 定州市| 淮北市| 平昌县| 无极县| 九龙坡区| 涿鹿县| 杂多县| 辽宁省| 行唐县|