一个传值的问题”*”与”*”
| 1 | /********************************************************* |
| 2 | * Desc:參數(shù)傳遞:使用引用傳遞指針和直接傳遞指針地址的區(qū)別 |
| 3 | * Author:charley |
| 4 | * DateTime:2010-12-7 11:00 |
| 02 | ***********************************************************/ |
| 03 | #include <iostream> |
| 04 | using namespace std; |
| 05 | ?? |
| 06 | /* |
| 07 | 函數(shù)聲明 |
| 08 | */ |
| 09 | void swapByRef(int *&,int *&); |
| 10 | void swapByPoi(int *,int *); |
| 11 | ?? |
| 12 | int main(void) |
| 13 | { |
| 14 | ????inti=10; |
| 15 | ????intj=20; |
| 16 | ????int*pi=&i; //pi指向i所在的內(nèi)存地址 |
| 17 | ????int*pj=&j;//pj指向j所在的內(nèi)存地址 |
| 18 | ?????? |
| 19 | ????//通過引用傳遞參數(shù),傳遞的是指針本身 |
| 20 | ????cout<<"調(diào)用swapByRef()之前:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl; |
| 21 | ????swapByRef(pi,pj); |
| 22 | ????cout<<"調(diào)用swapByRef()之后:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl; |
| 23 | ?????? |
| 24 | ????cout<<"**********************"<<endl; |
| 25 | ?? |
| 26 | ????//通過指針來傳遞參數(shù),傳遞的是指針地址 |
| 27 | ????cout<<"調(diào)用swapByPoi()之前:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl; |
| 28 | ????swapByPoi(&i,&j); |
| 29 | ????//或者直接 swapByPoi(pi,pj); |
| 30 | ????cout<<"調(diào)用swapByPoi()之后:pi="<<pi<<",*pi="<<*pi<<";pj="<<pj<<",*pj="<<*pj<<endl; |
| 31 | ?? |
| 32 | ????getchar(); |
| 33 | ????return0; |
| 34 | } |
| 35 | ?? |
| 36 | /* |
| 37 | 通過引用傳遞參數(shù): |
| 38 | 參數(shù)為整型指針的引用, |
| 39 | 引用是指針的一個別名,傳遞時不需要在內(nèi)存中分配空間來接收參數(shù) |
| 40 | 參考:swapByRef(int &v1,int &v2) |
| 41 | */ |
| 42 | void swapByRef(int *&v1,int *&v2) |
| 43 | { |
| 44 | ????int*temp=v1;//指針賦值,指針執(zhí)行的地址變化了 |
| 45 | ????v1=v2; |
| 46 | ????v2=temp; |
| 47 | } |
| 48 | ?? |
| 49 | /* |
| 50 | 通過指針來傳遞參數(shù): |
| 51 | 參數(shù)為整型指針變量 |
| 52 | 內(nèi)存存需要為形參分配空間來接收傳進來的指針地址 |
| 53 | 參考:swapByPoi(int v1,int v2) |
| 54 | */ |
| 55 | void swapByPoi(int *v1,int *v2) |
| 56 | { |
| 57 | ????inttemp=*v1; //操作指針指向的內(nèi)容,指針執(zhí)行的地址未變化 |
| 58 | ????*v1=*v2; |
| 59 | ????*v2=temp; |
| 60 | } |
執(zhí)行結(jié)果:
?
從結(jié)果可以看出:
1. swapByRef方法是直接交換參數(shù)的指針執(zhí)行的地址,所以指針指向的內(nèi)容也換了
2. swapByPoi方法只是操作指針指向的內(nèi)容,指針執(zhí)行的地址未變化
?
?
#include <stdio.h>
void swap(int x,int y)//這是錯誤的寫法
{
int temp;
temp=x;
x=y;
y=temp;
}
int main()
{
int a=5,b=8;
swap(a,b);
printf("%d %d\n",a,b);
return 0;
}
代碼很容易理解,就是交換2個變量a和b的值并輸出,但是運行后我們發(fā)現(xiàn)輸出結(jié)果不是"8 5"而依舊是"5 8",也就是說交換函數(shù)并沒有將2個變量的值交換,這是為什么呢?
我們知道,C語言中整型變量的形式參數(shù)傳遞的是值而不是地址,也就是形式參數(shù)實際上是復制了實際參數(shù)的值進入函數(shù)運算的,而被復制的實際參數(shù)的值并沒有改變。就這段代碼來說,就是形參x復制了a的值變成5,形參y復制了b的值變成8,然后在swap函數(shù)中進行交換,使得x=8,y=5,但實際上a和b的值并沒有被交換,這也就是為什么這段代碼并沒有實現(xiàn)交換的原因。
那么怎么解決呢?
先前我們說了C語言中整型變量的形式參數(shù)傳遞的是值而不是地址,那么現(xiàn)在我們就讓它傳遞地址,直接交換實際參數(shù)的值。
#include <stdio.h>
void swap(int *x,int *y)//使用指針傳遞地址
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}
int main()
{
int a=5,b=8;
swap(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
我們使用指針變量來進行地址傳遞,形式參數(shù)為變量a和b的地址,swap函數(shù)直接交換a和b的地址所指向的值。這里一定注意形式參數(shù)傳遞的是地址而不是值
?
?
?
C++引用&和指針在作為形參時的區(qū)別
int n;
int &m = n;
在C++中,多了一個C語言沒有的引用聲明符&,如上,m就是n的引用,簡單的說m就是n的別名,兩者在內(nèi)存中占同樣的位置,不對m開辟新的內(nèi)存空間,對m的任何操作,對n來說是一樣的。
對于引用,有以下三條規(guī)則:
(1)引用被創(chuàng)建的同時必須被初始化(指針則可以在任何時候被初始化)。
(2)不能有NULL 引用,引用必須與合法的存儲單元關聯(lián)(指針則可以是NULL)。
(3)一旦引用被初始化,就不能改變引用的關系(指針則可以隨時改變所指的對象)。
?
假如在一個函數(shù)中動態(tài)申請內(nèi)存空間,用指針和用引用作形參會得到不同的結(jié)果,如下面的例子:
void fun(int* b){? //用指針做形參
?b = (int*)malloc(sizeof(int)*3);
?for(int i=0; i<3; i++){
??a[i] = i;
?}
}
void fun(int* &b){??//用引用做形參
?b = (int*)malloc(sizeof(int)*3);
?for(int i=0; i<3; i++){
??b[i] = i;
?}
}
如果在main函數(shù)中定義了一個int型的空指針并分別作為實參傳入,如下:
int main(){
?int *a = NULL;
?fun(a);
?for(int i=0; i<3; i++){
??cout << a[i] << " ";
?}
?cout << "\n";
?return 0;
}
結(jié)果用指針的函數(shù)會出現(xiàn)內(nèi)存訪問出錯,用引用的函數(shù)則運行正常并正確輸出1 2 3.
這是因為:
1.指針雖然是地址傳遞,但實際上也是在函數(shù)中又定義了一個新的指針讓其與傳入的指針指向同一地址。但兩個指針本身作為變量在內(nèi)存中的存放地址是不同的,就是說這是兩個不同的變量,只是內(nèi)容(即所指地址)相同。
2.在函數(shù)中對新定義的指針動態(tài)申請內(nèi)存,但是當函數(shù)結(jié)束后,申請的內(nèi)存的生命周期也就結(jié)束了,所以當回到主函數(shù)時,作為實參的指針地址和內(nèi)容都沒有變化。仍然是個空指針,對其進行訪問自然出現(xiàn)了內(nèi)存讀錯誤了。
假如在main函數(shù)中這樣寫:
int *a = (int*)malloc(sizeof(int)*3);
就不會出現(xiàn)內(nèi)存讀錯誤了,但是輸出結(jié)果還是錯誤的,道理也是一樣的。
3.用引用作為實參傳入時,fun函數(shù)中的b其實就是主函數(shù)中a的別名(或者叫外號),反正就是操作完全相同,地址相同,內(nèi)容相同的一個變量,所以當fun函數(shù)返回時,對b的操作在主函數(shù)中對a同樣有效。
?
再看一個例子:
int *a = NULL;
char* b = (char*)a;
?
int *a = NULL;
char* &b = (char*)a;
這一次是在編譯階段的區(qū)別:
用指針可以通過編譯,而用引用則不可以,提示類型轉(zhuǎn)換出錯。
?
通過這兩個例子可以看出,指針比引用靈活,也更加危險。
?
摘自『高質(zhì)量c++編程』
條款一:指針與引用的區(qū)別
指針與引用看上去完全不同(指針用操作符’*’和’->’,引用使用操作符’.’),但是它們似乎有相同的功能。指針與引用都是讓你間接引用其他對象。你如何決定在什么時候使用指針,在什么時候使用引用呢?
首先,要認識到在任何情況下都不能用指向空值的引用。一個引用必須總是指向某些對象。因此如果你使用一個變量并讓它指向一個對象,但是該變量在某些時候也可能不指向任何對象,這時你應該把變量聲明為指針,因為這樣你可以賦空值給該變量。相反,如果變量肯定指向一個對象,例如你的設計不允許變量為空,這時你就可以把變量聲明為引用。
?
PS:引用在定義時不可加const,否則編譯出錯,在形參前面則可以加const以確保在函數(shù)中該變量不會被修改。
?
個人認為:其實形參建立的是一個新的地址,只是這地址是實參內(nèi)容的一個COPY,假如實參為p,形參就為_p;
總結(jié)
以上是生活随笔為你收集整理的一个传值的问题”*”与”*”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: charset参数 sqluldr2_S
- 下一篇: 再论递归