C++基礎之引用與指針的區別與聯系、常引用使用時應注意的問題


什么是引用?
引用就是對變量起一個別名,而變量還是原來的變量,並沒有重新定義一個變量。例如下面的例子:
 
 1 #include<iostream>
 2 using namespace std;
 3  
 4  
 5 int main()
 6 {
 7       int a = 10;
 8       int& n = a;
 9       cout<<a<<endl;
10       cout<<n<<endl;
11       cout<<&a<<endl;
12       cout<<&n<<endl;
13  
14       return 0;
15 }

 

 程序的運行結果為:

 

 

我們可以看到變量a和變量a的引用(別名)n所指向的就是同一片空間,而且別名n並沒有創建一個新的變量
 
在引用的時候我們應該注意一些問題:
1.一個變量可以有多個別名
2.引用必須初始化
3.引用只可以在變量初始化的時候引用一次,之后不可以在引用其他的變量(這個想要引用其他的變量幾乎是無法實現,反正我沒辦法)
 常引用
現在我們了解了什么是引用,而常引用是非常容易出現錯誤的一種引用,下面我們展開討論
以下代碼就是相關的用法:
 1 int main()
 2 {
 3       int d1 = 4;
 4       const int & d2 = d1;
 5       d1 = 5;             // d1改變d2的值也會改變。
 6 //    d2 = 6;             // 不能給常量(不能被修改的量)賦值
 7       const int d3 = 1;
 8       const int & d4 = d3;
 9 //    int&d5 = d3;
10       const int & d6 = 5; // 常量具有常性,只有常引⽤可以引⽤常量
11       double d7 = 1.1;
12 //    int& d8 = d7; //d7是double類型,d8是int,d7賦值給d8時要生成一個臨時變量
13       //也就是說d8引⽤的是這個帶有常性的臨時變量,所以不能賦值。
14       const int& d9 = d7;
15       return 0;
16 }
 
從以上的代碼中我們就可以知道const引用時應該注意的問題。
 
引用可以作為函數的參數也可以作為函數的返回值來使用,但是我們在使用的時候應該注意些什么呢?
1.引用作為函數的參數時
       在函數傳參的時候,在C語言中有兩種方式,一種是值傳遞,還有一種是址傳遞,也就是指針傳遞,而在C++中我們則引入了引用傳遞。這三種傳遞的方式各有各的特點的,這里我們着重說一下引用傳遞的特點
 1 #include<iostream>
 2 using namespace std;
 3 #include <Windows.h>
 4 struct BigData
 5 {
 6       int array [1000];
 7 };
 8 void DealBigData1(BigData& x)
 9 {
10       x.array[0] = 0;
11       x.array[1] = 1;
12       x.array[2] = 2;
13 }
14 void DealBigData2 (BigData x)
15 {
16       x.array [0]= 0;
17       x.array [1]= 1;
18       x.array [2]= 2;
19 }
20 void TestReference()
21 {
22       BigData bd ;
23       int begin = GetTickCount ();
24       for (int i = 0; i < 1000000; ++i )
25       {
26             DealBigData1(bd);
27       }
28       int end = GetTickCount ();
29       cout<<"cost time:" <<end - begin<<endl ;
30       begin = GetTickCount ();
31       for (int i = 0; i < 1000000; ++i )
32       {
33             DealBigData2(bd);
34       }
35       end = GetTickCount ();
36       cout<<"cost time:" <<end - begin<<endl ;
37 }
38 int main()
39 {
40       TestReference();
41       return 0;
42 }

 

以上代碼的運行結果為:
 
 
從運行結果我們不難看出相比於傳值而言,傳引用無疑極大地提升了程序的性能。
 
2.引用作為函數的返回值時
 
 1 int& Add (int d1, int d2)
 2 {
 3 int ret = d1 + d2;
 4 return ret ;
 5 }
 6 void test()
 7 {
 8 int a = 3, b = 4;
 9 int c = Add( a, b );
10 cout<<"c:" <<c<< endl;
11 }

 

上面這段代碼是錯誤的用法,因為用引用接收了一個局部或臨時變量的地址,在我們編譯的時候回報出如下的警告:
 
 
       這里是因為函數在返回的時候會創建一個臨時變量,而我們在以引用作為函數的返回值的時候,引用的是這個臨時變量,我們都知道臨時變量在函數運行完畢后會銷毀的,那樣這種寫法毫無疑問是錯誤的不推薦的。
而下面的代碼則是以傳值作為函數的返回值,是正確的,當我們要以引用作為函數的返回值的時候,我們應該return一個以引用傳遞的參數,那樣也就是正確的。
 1 int Add1 (int a, int b)
 2 {
 3       int ret = a + b;
 4       return ret;
 5 }
 6 int& Add2(int& a, int b)
 7 {
 8       int ret = a + b;
 9       return ret;
10 }
11 void test1()
12 {
13       int ret = Add1(1, 2);
14       cout<<"ret:" <<ret<< endl;
15 }
16 void test2()
17 {
18       int a = 3, b = 4;
19       int c = Add2( a, b );
20       cout<<"c:" <<c<< endl;
21 }
22 int main ()
23 {
24       test1();
25       test2();
26       return 0;
27 }
 
我們查看上面兩個函數以傳值作為函數返回值和傳引用作為函數返回值時的匯編有何不同,如下圖:

 

我們不難發現傳值返回的時候是把ret的值放入了eax寄存器中,而傳引用返回的時候是把ret的地址放進了eax寄存器中
因此我們應該在使用引用作為函數的返回值的時候應該注意:
1.不要返回⼀個臨時變量的引⽤。
2. 如果返回對象出了當前函數的作⽤域依舊存在,則最好使⽤引⽤返回,因為這樣更⾼效
 
在C語言中有指針,而C++中有應用,那么指針與引用究竟有什么區別與聯系呢?
1. 引⽤只能在定義時初始化⼀次,之后不能改變指向其它變量(從⼀⽽終);指
針變量的值可變。
2. 引⽤必須指向有效的變量,指針可以為空。
3. sizeof指針對象和引⽤對象的意義不⼀樣。 sizeof引⽤得到的是所指向的變量的
⼤⼩,⽽sizeof指針是對象地址的⼤⼩。
4. 指針和引⽤⾃增(++)⾃減(--)意義不⼀樣。
5. 相對⽽⾔,引⽤⽐指針更安全。
所以在使用指針和引用的時候我們應該知道指針雖然⽐引⽤更靈活,但是也更危險。使⽤指針時⼀定要注意檢查指針是否為空。指
針所指的地址釋放以后最好置0,否則可能存在野指針問題。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM