日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++Primer:函数(参数传递:引用形参)

發(fā)布時(shí)間:2025/3/15 c/c++ 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++Primer:函数(参数传递:引用形参) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.問題的引入

考慮下面不適宜復(fù)制實(shí)參的例子,該函數(shù)希望交換兩個(gè)實(shí)參的值:

<span style="font-size:18px;">void swap(int v1, int v2) {int temp = v2;v2 = v1;v1 = temp; } int main() {int i = 10;int j = 20;cout << "Before swap():\ti: "<< i << "\tj: " << j << endl;swap(i, j);cout << "After swap():\ti: "<< i << "\tj: " << j << endl;return 0; }</span>

編譯并執(zhí)行程序,產(chǎn)生如下輸出結(jié)果:
Before swap(): i: 10 ?j: 20
After swap(): ? ?i: 10 ?j: 20

這個(gè)例子期望改變實(shí)參本身的值。但是對于上述的函數(shù)定義,swap無法影響實(shí)參本身。執(zhí)行swap時(shí),只交換了實(shí)參的局部副本,而傳遞swap的實(shí)參并沒有修改。

為了使swap函數(shù)以期望的方式進(jìn)行工作,交換實(shí)參的值,需要將形參定義為引用類型:

<span style="font-size:18px;">// ok: swap acts on references to its arguments void swap(int &v1, int &v2) { int tmp = v2; v2 = v1; v1 = tmp; }</span>與所有的引用一樣,引用形參直接關(guān)聯(lián)所綁定的實(shí)參,他是實(shí)參的一個(gè)別名,而不是這些對象所謂的副本。定義引用時(shí),必須用與該引用綁定的對象初始化該引用。引用形參完全以相同的方式進(jìn)行工作。每次調(diào)用該函數(shù)時(shí),引用形參被創(chuàng)建并與相應(yīng)的實(shí)參關(guān)聯(lián)。

此時(shí),調(diào)用該函數(shù)時(shí),swap(i,j);

形參v1只是對象i的另一個(gè)名字,而v2則是對象j的另外一個(gè)名字。對v1的任何修改實(shí)際上也是對i的修改。所以此時(shí)可以完成兩個(gè)值的交換任務(wù)。

從C語言背景轉(zhuǎn)到C++的我們習(xí)慣通過傳遞指針來實(shí)現(xiàn)對實(shí)參的訪問。在C++中,使用引用形參更安全和更自然。

2.使用引用形參返回額外的信息

通過對上例的討論,可以理解如何利用引用形參讓函數(shù)修改實(shí)參的值。引用形參的另一種用法是向主調(diào)函數(shù)返回額外的結(jié)果。函數(shù)只能返回單個(gè)值,但有些時(shí)候,函數(shù)有不止一個(gè)的內(nèi)容需要返回。例如,定義一個(gè) find_val 函數(shù)。在一個(gè)整型 vector 對象的元素中搜索某個(gè)特定值。如果找到滿足要求的元素,則返回指向該元素的迭代器;否則返回一個(gè)迭代器,指向該 vector 對象的 end 操作返回的元素。此外,如果該值出現(xiàn)了不止一次,我們還希望函數(shù)可以返回其出現(xiàn)的次數(shù)。在這種情況下,返回的迭代器應(yīng)該指向具有要尋找的值的第一個(gè)元素。如何定義既返回一個(gè)迭代器又返回出現(xiàn)次數(shù)的函數(shù)?可以定義一種包含一個(gè)迭代器和一個(gè)計(jì)數(shù)器的新類型。而更簡便的解決方案是給 find_val 傳遞一個(gè)額外的引用實(shí)參,用于返回出現(xiàn)次數(shù)的統(tǒng)計(jì)結(jié)果:

<span style="font-size:18px;">// returns an iterator that refers to the first occurrence of value // the reference parameter occurs containn a second return value vector<int>::const_iterator find_val(vector<int>::const_iterator beg, vector<int>::const_iterator end, <span style="color:#cc0000;"><strong> int value</strong></span>, // the value we want<strong><span style="color:#ff0000;">vector<int>::size_type &occurs</span></strong>) // number of times it occurs {// res_iter will hold first occurrence, if anyvector<int>::const_iterator res_iter = end;<span style="color:#ff0000;"><strong>occurs = 0;</strong></span> // set occurrence count parameter ///引用,即別名,我們可以在主函數(shù)體中查到for ( ; beg != end; ++beg)if (*beg == value) {// remember first occurrence of valueif (res_iter == end){ res_iter = beg;}++occurs; // increment occurrence count}return res_iter; // count returned implicitly in occurs }</span>

it = find_val(ivec.begin(), ivec.end(), 42, ctr);

調(diào)用 find_val 時(shí),需傳遞四個(gè)實(shí)參:一對標(biāo)志 vector 對象中要搜索的元素范圍的迭代器,所查找的值,以及用于存儲(chǔ)出現(xiàn)次數(shù)的size_type 類型對象。假設(shè) ivec 是 vector<int>類型的對象,it 是一個(gè)適當(dāng)類型的迭代器,而 ctr 則是 size_type 類型的變量。

調(diào)用后,ctr 的值將是 42 出現(xiàn)的次數(shù),如果 42 在 ivec 中出現(xiàn)了,則 it將指向其第一次出現(xiàn)的位置;否則,it 的值為 ivec.end(),而 ctr 則為 0

3. 利用const引用避免復(fù)制(const int&)

向函數(shù)傳遞大型對象時(shí),需要使用引用形參,這是引用形參適用的另一種情況。雖然復(fù)制實(shí)參對于內(nèi)置數(shù)據(jù)類型的對象或者規(guī)模較小的類類型對象來說沒有什么問題,但是對于大部分的類類型或者大型數(shù)組,它的效率太低了;此外,也會(huì)注意某些類類型是無法復(fù)制的。使用引用形參,函數(shù)可以直接訪問實(shí)參對象,而無須復(fù)制它。

舉個(gè)例子: 我們需要編寫這樣一個(gè)功能:我們要比較兩個(gè)string對象長度。這個(gè)函數(shù)需要訪問每個(gè)string對象的大小,但是沒有必要修改這些對象。由于string對象可能相當(dāng)長,所以應(yīng)該避免采用復(fù)制操作。此時(shí),采用const 引用就非常合適。 <span style="font-size:18px;">// compare the length of two strings bool isShorter(<strong><span style="color:#ff0000;">const string&</span></strong> s1, <span style="color:#ff0000;"><strong>const string&</strong></span> s2) {return s1.size() < s2.size(); }</span>注意:如果使用引用形參的唯一目的是避免復(fù)制實(shí)參,則應(yīng)將形參定義為const引用

4.更靈活的指向const的引用

如果函數(shù)具有普通的非const引用形參,則顯然不能通過從const對象進(jìn)行調(diào)用。畢竟,此時(shí)函數(shù)可以修改傳遞進(jìn)來的對象,這樣就違背了實(shí)參的const特性。但比較容易忽略的是,調(diào)用這樣的函數(shù)(非const引用形參)時(shí),傳遞一個(gè)右值或具有需要轉(zhuǎn)換的對象同樣是不允許的 <span style="font-size:18px;">// function takes a non-const reference parameter int incr(int &val) {return ++val; } int main() {short v1 = 0;const int v2 = 42;int v3 = incr(v1); // error: v1 is not an intv3 = incr(v2); // error: v2 is const<strong><span style="color:#ff0000;">v3 = incr(0); // error: literals are not lvalues</span></strong>v3 = incr(v1 + v2); // error: addition doesn't yield an lvalueint v4 = incr(v3); // ok: v3 is a non const object type int }</span>問題的關(guān)鍵在于:非const引用形參只能與完全同類型的非const對象關(guān)聯(lián)!!! 舉一個(gè)例子: <span style="font-size:18px;">// returns index of first occurrence of c in s or s.size() if c isn't in s // Note: s doesn't change, so it should be a reference to const string::size_type find_char(<span style="color:#ff0000;"><strong>string &s</strong></span>, char c) {string::size_type i = 0;while (i != s.size() && s[i] != c)++i; // not found, look at next characterreturn i; }</span>

if (find_char("Hello World", 'o')) // ...

雖然字符串字面值可以轉(zhuǎn)換為string對象,但是上述的調(diào)用仍然會(huì)導(dǎo)致編譯失敗。盡管函數(shù)并沒有修改這個(gè)形參的值,但是這樣的定義帶來的問題是不能通過字符串字面值調(diào)用函數(shù)

應(yīng)該說,更鼓勵(lì)將不加以修改的實(shí)參定義為const引用,因?yàn)閷⑿螀⒍x為非const引用,將毫不必要地限制了這些函數(shù)的使用(比如字面值字符串查找某一元素)!

注意:應(yīng)當(dāng)將不需要修改的引用形參定義為const引用。普通的非const引用形參在使用時(shí)非常不靈活。非const形參既不允許const對象初始化,也不能用字面值或產(chǎn)生右值的表達(dá)式實(shí)參初始化,大大地限制了函數(shù)功能。

5.傳遞指向指針的引用

假設(shè)想編寫一個(gè)與前面交換兩個(gè)整數(shù)的 swap 類似的函數(shù),實(shí)現(xiàn)兩個(gè)指針的交換。已知需用 * 定義指針,用 & 定義引用。現(xiàn)在,問題在于如何將這兩個(gè)操作符結(jié)合起來以獲得指向指針的引用。這里給出一個(gè)例子:

<span style="font-size:18px;">// swap values of two pointers to int void ptrswap(int* &v1, int* &v2) {int *tmp = v2;v2 = v1;v1 = tmp; }</span>形參: int* &v1;
應(yīng)該從右至左理解:v1是一個(gè)引用(別名),與指向int型對象的指針相關(guān)聯(lián)。也就是說,v1只是傳遞金ptrswap函數(shù)的任意指針的別名。

<span style="font-size:18px;">int main() {int i = 10;int j = 20;int *pi = &i; // pi points to iint *pj = &j; // pj points to jcout << "Before ptrswap():\t*pi: "<< *pi << "\t*pj: " << *pj << endl;ptrswap(pi, pj); // now pi points to j; pj points to icout << "After ptrswap():\t*pi: "<< *pi << "\t*pj: " << *pj << endl;return 0; }</span>解釋:形參實(shí)參關(guān)系可以理解為 int* ?&v1 (pi); ?實(shí)際上,傳進(jìn)來了兩個(gè)指針,最終完成的是指針的交換!

即指針的值被交換了。在調(diào)用 ptrswap 時(shí),pi 指向 i,而 pj 則指向 j。在 ptrswap 函數(shù)中, 指針被交換, 使得調(diào)用 ptrswap 結(jié)束后, pi 指向了原來 pj所指向的對象。換句話說,現(xiàn)在 pi 指向 j,而 pj 則指向了 i。

總結(jié)

以上是生活随笔為你收集整理的C++Primer:函数(参数传递:引用形参)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品扒开腿做爽爽爽视频 | 拔插拔插海外华人免费视频 | 一级片大片 | 国产精品免费视频观看 | 日韩在线中文字幕视频 | 又黄又色的网站 | 国产日韩精品中文字无码 | 好紧好爽再浪一点视频 | 日本中文字幕在线观看视频 | 久久久在线视频 | 露胸app | 精品国产96亚洲一区二区三区 | 久草精品视频 | 香蕉视频在线视频 | 久草新免费 | 亚洲av无一区二区三区 | 黄网在线免费观看 | 成人网址在线观看 | 国产日韩三级 | 国产精品无码电影在线观看 | 无码人妻精品一区二区三区在线 | 热久久91 | 五月丁香久久婷婷 | 国产宾馆实践打屁股91 | 一区二区精品区 | 中文毛片无遮挡高潮免费 | 日本做爰高潮又黄又爽 | 国产在线免费视频 | 亚洲第一视频网 | 久久精品第一页 | 中国丰满熟妇xxxx性 | 欧美日韩在线免费视频 | 亚洲精品乱码久久久久久蜜桃不卡 | 男人午夜影院 | 中文字幕高清在线免费播放 | 中文字幕在线高清 | 男女黄床上色视频免费的软件 | 我要看一级黄色片 | 欧美亚洲精品天堂 | 女人扒开屁股让男人桶 | 国产日韩精品电影 | av在线播放器 | 国产精品人人爽 | 欧美色图俺去了 | 欧美一区二区三区免费观看 | av导航大全| 筱田优全部av免费观看 | 四虎一国产精品一区二区影院 | 日韩精品一区二区三区国语自制 | 日本黄色成人 | 伊人免费在线观看 | 婷婷玖玖| 中文字幕观看av | 中文字幕看片 | 日本人dh亚洲人ⅹxx | 性欧美大战久久久久久久 | www性 | 欧美性欧美zzzzzzzzz | 国产在线视视频有精品 | 国产女人18水真多毛片18精品 | 中文在线а√天堂 | 丝袜+亚洲+另类+欧美+变态 | 久久久久国产精品 | 91视频免费网址 | 国产一区导航 | 国产性猛交╳xxx乱大交 | 一区二区欧美视频 | 亚洲天堂精品在线 | 男女无遮挡做爰猛烈视频 | 久久亚洲av永久无码精品 | 人妖和人妖互交性xxxx视频 | 精品一区二区三区电影 | 国产又爽又黄免费软件 | 欧美在线一二三区 | 国产精品久久久久久久久久久久久久久 | 91蝌蚪在线观看 | av导航福利 | 中文字幕超清在线观看 | 亚洲第一区在线播放 | 在线日韩一区二区 | www日韩av | 成人精品国产免费网站 | 日本jizzjizz| 日本69少妇| 成人做爰9片免费视频 | 欧美日本高清 | 国产+高潮+白浆+无码 | 极品三级 | 日本天堂免费a | 黄色亚洲视频 | 日本做爰全过程免费看 | 91香蕉视频污污 | 亚洲av成人无码一二三在线观看 | 高h视频在线播放 | 白浆影院 | 99精品人妻国产毛片 | 国产无码日韩精品 | 亚洲精品a区 | 欧美v亚洲 |