深入浅出之函数的参数传递方式
1 按值傳遞
按值傳遞也稱傳值,其傳遞形式是形參為普通變量,實(shí)參為表達(dá)式或變量,實(shí)參向形參賦值。
按值傳遞的特點(diǎn)是參數(shù)傳遞后,實(shí)參和形參不再有任何聯(lián)系。需要注意的是,此時(shí)實(shí)參是表達(dá)式,故形參不可能給實(shí)參賦值。函數(shù)被調(diào)用時(shí),系統(tǒng)為形參分配相應(yīng)的存儲(chǔ)單元,用于接受實(shí)參傳遞的數(shù)據(jù)。函數(shù)調(diào)用期間,形參和實(shí)參各自擁獨(dú)立的存儲(chǔ)丹云。函數(shù)電泳結(jié)束,系統(tǒng)回收分配給形參的存儲(chǔ)單元。
傳值調(diào)用的優(yōu)點(diǎn)是函數(shù)調(diào)用對(duì)其外界的變量無(wú)影響,最多只能用return返回一個(gè)值,函數(shù)獨(dú)立性強(qiáng)。
#include <QCoreApplication> #include<iostream>using namespace std; // 函數(shù)聲明 void swap(int x, int y);int main(int argc, char *argv[]) {QCoreApplication aa(argc, argv);// 局部變量聲明int a = 100;int b = 200;cout << a << endl;cout << b << endl;// 調(diào)用函數(shù)來(lái)交換值swap(a, b);cout << a << endl;cout << b << endl;return aa.exec(); }/*!* \brief swap* \param x* \param y*/ void swap(int x, int y) {int temp;temp = x; /* 保存 x 的值 */x = y; /* 把 y 賦值給 x */y = temp; /* 把 x 賦值給 y */return; } 輸出結(jié)果: 100 200 100 200雖然在函數(shù)內(nèi)改變了 a 和 b 的值,但是實(shí)際上 a 和 b 的值沒(méi)有發(fā)生變化。?
2 按引用傳遞
按引用傳遞又稱傳引用。引用即變量的別名,對(duì)別名的訪問(wèn)就是對(duì)別名所關(guān)聯(lián)的訪問(wèn),直接傳入對(duì)象而無(wú)需傳遞對(duì)象的地址,反之亦然,&稱為引用符。
int i; int &ai = i;// 定義int型引用ai是變量i的別名 ai = 15;//此時(shí)i的值也為15使用引用應(yīng)注意以下幾點(diǎn):
1) 定義引用時(shí),應(yīng)同時(shí)對(duì)它初始化,使它與一個(gè)類型相同的已有變量關(guān)聯(lián)。
2) 一個(gè)引用與某變量關(guān)聯(lián);
3)引用主要用做函數(shù)的形參和返回值?
#include <QCoreApplication>int max(int &x,int &y) {return x>y?x:y; }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);int x = 10,y = 9;int res = max(x,y); // x,y為實(shí)參qDebug("%d",res);return a.exec(); }x是實(shí)參a的醫(yī)用,y是實(shí)參b的引用,他們占用同一個(gè)內(nèi)存單元,知識(shí)名稱不同。引用的主要特點(diǎn)如下:
1) 高效的傳遞參數(shù),避免了傳值方式中的拷貝構(gòu)造。引用傳遞實(shí)際上是傳地址;
2) return語(yǔ)句最多返回一個(gè)值,而使用引用的形式可以修改多個(gè)實(shí)參變量的值;?
3)使用引用形參可以避免拷貝大的類型的類類型對(duì)象或容器類型對(duì)象;
?3 按指針?lè)绞?/h1>
指針傳遞本質(zhì)上和值傳遞差不多,實(shí)際上是把實(shí)際的指針參數(shù)傳遞給函數(shù)中創(chuàng)建的形參指針。不同的地方在于,指針傳遞的情況時(shí),可以通過(guò)再函數(shù)中通過(guò)形參指針的間址訪問(wèn)對(duì)實(shí)際變量做出更改,這是值傳遞無(wú)法做到的。
指針的行為和其他非引用類型一樣。當(dāng)執(zhí)行指針的拷貝操作時(shí),拷貝的是指針的值。拷貝之后,兩個(gè)指針是不同的指針。可以通過(guò)指針修改所指對(duì)象的值,傳入的是變量對(duì)象的地址的拷貝。
#include <QCoreApplication>int max(int *x,int *y) {return *x>*y?*x:*y; }int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);int x = 10,y = 9;int res = max(&x,&y); // x,y為實(shí)參qDebug("%d",res);return a.exec(); }4?指針和引用的區(qū)別?
(1)指針:指針是一個(gè)變量,只不過(guò)這個(gè)變量存儲(chǔ)的是一個(gè)地址,指向內(nèi)存的一個(gè)存儲(chǔ)單元;而引用跟原來(lái)的變量實(shí)質(zhì)上是同一個(gè)東西,只不過(guò)是原變量的一個(gè)別名而已。如:
int a=1;int *p=&a;
int a=1;int &b=a;
上面定義了一個(gè)整形變量和一個(gè)指針變量p,該指針變量指向a的存儲(chǔ)單元,即p的值是a存儲(chǔ)單元的地址。
而下面2句定義了一個(gè)整形變量a和這個(gè)整形a的引用b,事實(shí)上a和b是同一個(gè)東西,在內(nèi)存占有同一個(gè)存儲(chǔ)單元。
(2)可以有const指針,但是沒(méi)有const引用;
(3)指針可以有多級(jí),但是引用只能是一級(jí)(int **p;合法 而 int &&a是不合法的)
(4)指針的值可以為空,但是引用的值不能為NULL,并且引用在定義的時(shí)候必須初始化;
(5)指針的值在初始化后可以改變,即指向其它的存儲(chǔ)單元,而引用在進(jìn)行初始化后就不會(huì)再改變了。
(6)"sizeof引用"得到的是所指向的變量(對(duì)象)的大小,而"sizeof指針"得到的是指針本身的大小;
(7)指針和引用的自增(++)運(yùn)算意義不一樣;
5 三種傳遞方式內(nèi)存分析?
#include "stdafx.h" #include <iostream>using namespace std;//值傳遞 void swap1(int p,int q) {int temp;temp=p;p=q;q=temp; }//指針傳遞,函數(shù)體內(nèi)只有指針值的變化 void swap2(int *p,int *q) {int temp;temp=*p;*p=*q;*q=temp; }//指針傳遞,函數(shù)體內(nèi)只有指針的變化 void swap3(int *p,int *q) {int *temp;temp=p;p=q;q=temp; }//引用傳遞 void swap4(int &p,int &q) {int temp;temp=p;p=q;q=temp; }int main() { int a=1,b=2;swap1(a,b);//swap2(&a,&b);//swap3(&a,&b);//swap4(a,b);cout<<a<<" "<<b<<endl;return 0; }5.1.值傳遞
swap1函數(shù)實(shí)現(xiàn)的值傳遞,值傳遞傳遞的是實(shí)際參數(shù)的一個(gè)副本,如果對(duì)這句話不理解,那一步步調(diào)試看下內(nèi)存分配情況。
執(zhí)行到48行時(shí),a和b的情況如下
接著進(jìn)入swap1函數(shù)體內(nèi),如下所示
可以看到的是,p和q的地址和a與b的地址不一樣,只是把a(bǔ)和b的值拷貝過(guò)去了,在swap1中對(duì)p和q操作只是對(duì)臨時(shí)分配的棧中內(nèi)容進(jìn)行操作,函數(shù)執(zhí)行完后形參就消失了,對(duì)原來(lái)的a和b不產(chǎn)生任何影響。所以swap1不能完成交換a和b值的功能
5.2.指針傳遞
swap2和swap3都是指針傳遞,swap2函數(shù)體內(nèi)交換了p和q指向地址的值,swap3函數(shù)體內(nèi)交換了p和q指向的地址。
先說(shuō)swap2,進(jìn)入swap2函數(shù)體內(nèi),如下所示
可以看到,形參指針p和q指向的是a和b的地址,而不是像值傳遞那樣將實(shí)參的值拷貝到另外分配的地址中,運(yùn)行到函數(shù)尾時(shí),如下圖
可以看到、指針p和q指向的地址沒(méi)變,但地址中的值變了,也即a和b地址中的變了,就是a和b的值成功交換,繼續(xù)調(diào)試可以看到正確的結(jié)果,如下圖
再來(lái)看swap3,swap3運(yùn)行到函數(shù)尾時(shí)的情況如下
可以看到p和q交換了地址,但最后函數(shù)執(zhí)行完后的結(jié)果又如下所示
a和b的值并未交換,這是為什么呢?
swap3中,形參p和q會(huì)保存在棧中,p指向a的地址,q指向b的地址,使用temp指針完成了p和q的地址交換,即p指向b的地址,q指向了a的地址,但a和b地址中的值并未發(fā)生變化,這與swap2不同,swap2中是p指向的地址中的值(就是a)與q指向的地址中的值(b)交換,所以swap2執(zhí)行完后a和b的值是交換了的。
5.3.引用傳遞
引用傳遞時(shí),對(duì)形參的操作等同于對(duì)實(shí)參的操作,即傳遞的不會(huì)是實(shí)參的副本,而就是實(shí)參,進(jìn)入swap4函數(shù)體內(nèi)如下所示
看到這個(gè)內(nèi)存分配,很明了了吧。最后會(huì)交換a和b的值。
參考:
總結(jié)
以上是生活随笔為你收集整理的深入浅出之函数的参数传递方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: u盘里面数据不见了怎么办 U盘数据不见了
- 下一篇: 深入浅出之数组