【C++】引用那些事(2)
阿新 • • 發佈:2019-01-07
一、傳值、傳引用效率比較
以值作為引數或者返回值型別,在傳參和返回期間,函式不會直接傳遞實參或者將變數本身直接返回,而是傳遞實
參或者返回變數的一份臨時的拷貝,因此用值作為引數或者返回值型別,效率是非常低下的,尤其是當引數或者返
回值型別非常大時,效率就更低。
#include <time.h> struct A { int a[10000]; }; void TestFunc1(A a) {} void TestFunc2(A& a) {} void TestRefAndValue() { A a; // 以值作為函式引數 size_t begin1 = clock(); for (size_t i = 0; i < 10000; ++i) TestFunc1(a); size_t end1 = clock(); // 以引用作為函式引數 size_t begin2 = clock(); for (size_t i = 0; i < 10000; ++i) TestFunc2(a); size_t end2 = clock(); // 分別計算兩個函式執行結束後的時間 cout << "TestFunc1(int*)-time:" << end1 - begin1 << endl; cout << "TestFunc2(int&)-time:" << end2 - begin2 << endl; } // 執行多次,檢測指標和引用在傳參方面的效率區別 int main() { for (int i = 0; i < 10; ++i) { TestRefAndValue(); } return 0; }
二、 指標和引用的作為返回值型別的效能比較
#include <time.h> struct A { int a[10000]; }; A a; A TestFunc1() { return a; } A& TestFunc2() { return a; } void TestReturnByRefOrValue() { // 以指標作為函式的返回值型別 size_t begin1 = clock(); for (size_t i = 0; i < 100000; ++i) TestFunc1(); size_t end1 = clock(); // 以引用作為函式的返回值型別 size_t begin2 = clock(); for (size_t i = 0; i < 100000; ++i) TestFunc2(); size_t end2 = clock(); // 計算兩個函式運算完成之後的時間 cout << "TestFunc1 time:" << end1 - begin1 << endl; cout << "TestFunc2 time:" << end2 - begin2 << endl; }// 測試執行10次,指標和引用作為返回值效率方面的區別 int main() { for (int i = 0; i < 10; ++i) TestReturnByRefOrValue(); return 0; }
通過上述程式碼的比較,發現引用和指標在作為傳參以及返回值型別上效率幾乎相同。
三、引用和指標的區別
1. 引用在定義時必須初始化,指標沒有要求
2. 引用在初始化時引用一個實體後,就不能再引用其他實體,而指標可以在任何時候指向任何一個同類型
實體
3. 沒有NULL引用,但有NULL指標
4. 在sizeof中含義不同:引用結果為引用型別的大小,但指標始終是地址空間所佔位元組個數(32位平臺下佔
4個位元組)
5. 引用自加即引用的實體增加1,指標自加即指標向後偏移一個型別的大小
6. 有多級指標,但是沒有多級引用
7. 訪問實體方式不同,指標需要顯式解引用,引用編譯器自己處理
8. 引用比指標使用起來相對更安全
在語法概念上引用就是一個別名,沒有獨立空間,和其引用實體共用同一塊空間。在底層實現上實際是有空間的,因為引用是按照指標方式來實現的。
在反彙編程式碼中,二者的實現是一樣的。
//引用
int main()
{
int a = 10;
int& ra = a;
cout<<"&a = "<<&a<<endl;
cout<<"&ra = "<<&ra<<endl;
return 0;
}
//指標
int main()
{
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
return 0;
}