6、效率比較
值和引用的作為返回值類型的性能比較:
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; } // 拷貝
// 引用返回
A& TestFunc2() { return a; } // 不拷貝
void TestReturnByRefOrValue()
{
// 以值作為函數(shù)的返回值類型
size_t begin1 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc1();
size_t end1 = clock();
// 以引用作為函數(shù)的返回值類型
size_t begin2 = clock();
for (size_t i = 0; i < 100000; ++i)
TestFunc2();
size_t end2 = clock();
// 計算兩個函數(shù)運(yùn)算完成之后的時間
cout << "TestFunc1 time:" << end1 - begin1 << endl;
cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
TestReturnByRefOrValue();
return 0;
}
由于傳值返回要拷貝,所以當(dāng)拷貝量大,次數(shù)多時,比較耗費(fèi)時間;而傳引用返回就不會,因為返回的就是別名。
對于返回函數(shù)作用域還在的情況,引用返回優(yōu)先。
引用傳參和傳值傳參效率比較 :
struct A { int a[10000]; };
void TestFunc1(A a) {}
void TestFunc2(A& 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ù)運(yùn)行結(jié)束后的時間
cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
TestRefAndValue();
}
還是引用快,因為引用減少拷貝次數(shù):
總結(jié):引用的作用主要體現(xiàn)在傳參和傳返回值
- 引用傳參和傳返回值,在有些場景下可以提高性能(大對象 and 深拷貝對象 – 之后會講)。
- 引用傳參和傳返回值,在對于輸出型參數(shù)和輸出型返回值很舒服。說人話就是形參改變,實參也改變 or 返回對象(返回值改變)。
7、常引用
const 修飾的是常變量,不可修改。
a本身都不能修改,b為a的引用,那么b也不可以修改,這樣就沒意義了。a是只讀,但是引用b具有可讀可寫的權(quán)利,該情況為權(quán)限放大,所以錯誤了。
這時,只要加 const 修飾 b ,讓 b 的權(quán)限也只有只讀,使得 權(quán)限不變 ,就沒問題了:
而如果原先變量可讀可寫,但是別名用 const 修飾,也是可以的,這種情況為 權(quán)限縮小 :
對于函數(shù)的返回值來說,也不能權(quán)限放大,例如:
int fun()
{
static int n = 0;
n++;
return n;
}
int main()
{
int& ret = fun(); // error
return 0;
}
這樣也是不行的,因為返回方式為 傳值返回 ,返回的是臨時變量,具有 常性 ,是不可改的;而引用放大了權(quán)限,所以是錯誤的;這時加 const 修飾就沒問題:
const int& ret = c(1, 2)
那么這種情況為什么不可以?
而這樣就可以了?
因為類型轉(zhuǎn)換會產(chǎn)生臨時變量 :
對于類型轉(zhuǎn)換來說,在轉(zhuǎn)換的過程中會產(chǎn)生一個個臨時變量,例如 double d = i,把i轉(zhuǎn)換后的值放到臨時變量中,把臨時變量給接收的值d
而臨時變量具有常性,不可修改,引用就加了寫權(quán)限,就錯了,因為 權(quán)限被放大了 。
小結(jié):對于引用,引用后的變量所具權(quán)限可以縮小或不變,但是不能放大(指針也適用這個說法)
作用 :在一些場景下,假設(shè) x 是一個大對象,或者是深拷貝對象,那一般都會用引用傳參,減少拷貝,如果函數(shù)中不改變 x ,盡量用 const 引用傳參。
這樣可以防止 x 被修改 ,而對于 const int& x 也可以接受權(quán)限對等或縮小的對象,甚至為常量:
結(jié)論 :const type& 可以接收各種類型的對象(變量、常量、隱式轉(zhuǎn)換)。對于輸出型參數(shù)用引用,否則用 const type&,更加安全。
8、指針和引用區(qū)別
從語法概念上來說,引用是沒有開辟空間的,而指針是開辟了空間的,但是從底層實現(xiàn)上來說,則又不一樣:
int main()
{
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
return 0;
}
匯編:
lea 是取地址:我們發(fā)現(xiàn)無論引用和指針,都會取地址,且這些過程和指針一樣。
其實從匯編上,引用其實是開空間的,并且實現(xiàn)方式和指針一樣,引用其實也是用指針實現(xiàn)的。
區(qū)別匯總:
- 引用概念上定義一個變量的 別名 ,指針存儲一個變量 地址。
- 引用 在定義時 必須初始化 ,指針最好初始化 ,但是不初始化也不會報錯。
- 引用在初始化時引用一個實體后 ,就不能再引用其他實體 ,而指針可以在任何時候指向任何一個同類型。
- 沒有NULL引用,但有NULL指針。
- 在sizeof中含義不同:引用結(jié)果為 引用類型的大小,但指針始終是 地址空間所占字節(jié)個數(shù) (32位平臺下占4個字節(jié))。
- 引用自加即引用的實體增加1,指針自加即指針向后偏移一個類型的大小。
- 有多級指針,但是沒有多級引用。
- 訪問實體方式不同,指針需要顯式解引用,引用編譯器自己處理。
- 引用比指針使用起來相對更安全。
以上全部是對c++引用的一個詳細(xì)解讀,希望大家受益良多哈。平時在寫代碼的時候多調(diào)試看看里面的原理,看看編譯器到底是怎么進(jìn)行運(yùn)行的,讓自己對編碼這塊更具有靈性!
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136824 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73651 -
面向?qū)ο?/span>
+關(guān)注
關(guān)注
0文章
64瀏覽量
9985
發(fā)布評論請先 登錄
相關(guān)推薦
評論