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

Visual C++教程之C++的語言資料概述免費(fèi)下載

C++程序設(shè)計(jì)教程之?dāng)?shù)據(jù)類型的詳細(xì)資料說明

C++程序設(shè)計(jì)教程之C++的初步知識的詳細(xì)資料說明

C++程序設(shè)計(jì)教程之?dāng)?shù)組的詳細(xì)資料說明

C++程序設(shè)計(jì)教程之指針的詳細(xì)資料說明

C++程序設(shè)計(jì)教程之基于對象的程序設(shè)計(jì)的詳細(xì)資料說明

C++程序設(shè)計(jì)的基礎(chǔ)知識初步了解C++的資料免費(fèi)下載

C++中的const和引用的討論
C++基礎(chǔ)語法中的引用、封裝和多態(tài)
c++引用詳細(xì)解說1

c++引用詳細(xì)解說2

c++引用詳細(xì)解說3

評論