兩者本質
引用是別名,指針是地址、實體
兩者區別
不同點 | 分析 |
---|---|
1.初始化要求不同 | 引用在創建的同時必須初始化,即引用到一個有效的對象,而指針在定義的時候不必初始化,可以在定義後面的任何地方重新賦值。 |
2.可修改性性不同 | 引用一旦被初始化爲指向一個對象,它就不能被改變爲另一個對象的引用;而指針在任何地方都可以改變爲指向另一個對象。給引用賦值並不是改變它和原始對象的綁定關係。 |
3.不存在NULL引用 | 引用不能使用指向空值的引用,它必須總是指向某個對象;而指針則可以是NULL,而不需要總是指向某些對象,可以把指針指向任意的對象,所以指針更加靈活,但是也更容易出錯。 |
4.測試需要的區別 | 由於引用不會指向空值,這意味着使用引用前不需要測試它的合法性,而指針則需要經常進行測試。因此使用引用的代碼效率比使用指針的效率要高。 |
5.應用的區別 | 如果是指一旦指向一個對象後就不會改變指向,那麼應該使用引用。如果有存在指向NULL(不指向任何對象)或在不同的時刻指向不同的對象這些可能性,應該使用指針更爲穩妥一些。 |
6.運算符的區別 | 指針和引用的自增(++)運算意義不同,引用自加即引用的實體增加1,指針自加即指針向後偏移一個類型的大小。 |
7.計算對象大象大小 | "sizeof 引用"得到的是所指向的變量(對象)的大小,而"sizeof 指針"得到的是指針本身的大小。 |
8.多級的區別 | 有多級指針,但是不存在多級引用,只能有一級引用。 |
9.訪問時的區別 | 引用訪問的是一個變量,是直接訪問的,而指針則是訪問一個變量則是在間接訪問的。 |
10.const的區別 | 引用沒有const,指針有const,const指針不可變。 |
兩者的相同點
指針指向一塊內存,它的內容是所知內存的的地址;引用則是某塊內存的別名。
int main()
{
int aa = 10;
int& wa = a;
cout<<"&aa = "<<&aa<<endl;
cout<<"&wa = "<<&wa<<endl;
return 0;
}
總的來說,引用即具有指針的效率,又具有變量使用的方便性和直觀性。
爲什麼傳引用比傳指針更安全
答:由於不存在空指針,並且引用一旦被初始化爲指向一個對象,它就不能改變爲另一個對象的引用,因此引用更爲安全。
對於指針來說,它可以隨時指向別的對象,並且可以不被初始化,或爲NULL,所以不安全,const指針任然存在空指針,並且有可能產生野指針。
指針:對於一個類型T,T就是指向T的指針類型,也就是一個T類型的變量能夠保存一個對象的地址,而類型T是可以加一些限定詞,如const等等。
char a='A';
char* p=&a;
引用:引用是一個對象別名,主要用於函數參數和返回值類型,符號X&標識X類型的引用。
int i=1;
int &r=1;
int x=r;
r=2;
int* p=&r;
做參數:
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
做返回值:
int& Test(int& a)
{
a += 10;
return a;
}
兩者做參數效率的比較:
#include <time.h>
struct A {
int a[10000];
};
void Test1(A a)
{}
void Test2(A& a)
{}
void Test3()
{
A a;
// 以指針作爲函數參數
size_t begin1 = clock();
for (size_t i = 0; i < 10000; ++i)
Test1(a);
size_t end1 = clock();
// 以引用作爲函數參數
size_t begin2 = clock();
for (size_t i = 0; i < 10000; ++i)
Test2(a);
size_t end2 = clock();
// 分別計算兩個函數運行結束後的時間
cout << "Test1(int*)-time:" << end1 - begin1 << endl;
cout << "Test2(int&)-time:" << end2 - begin2 << endl; }
// 運行多次,檢測指針和引用在傳參方面的效率區別
int main()
{
for (int i = 0; i < 10; ++i)
{
Test3();
}
return 0;
}
兩者做返回值效率的比較
#include <time.h>
struct A {
int a[10000];
};
A a; A Test1()
{
return a;
}
A& Test2()
{
return a;
}
void Test3()
{
// 以指針作爲函數的返回值類型
size_t begin1 = clock();
for (size_t i = 0; i < 100000; ++i)
Test1();
size_t end1 = clock();
// 以引用作爲函數的返回值類型
size_t begin2 = clock();
for (size_t i = 0; i < 100000; ++i)
Test2();
size_t end2 = clock();
// 計算兩個函數運算完成之後的時間
cout << "Test1 time:" << end1 - begin1 << endl;
cout << "Test2 time:" << end2 - begin2 << endl;
}
// 測試運行10次,指針和引用作爲返回值效率方面的區別
int main()
{
for (int i = 0; i < 10; ++i)
Test3();
system("pause");
return 0;
}
由效率測試可以看出,在效率方面,無論是引用做參數還是返回值,時間花費的相對更少。