總結一下指針值傳遞、地址傳遞和引用傳遞 :
指針的值傳遞
//test.c
#include <cstdio>
#include <cstring>
#include <cassert>
void fun(char* p){
p = (char*)malloc(sizeof(char));
assert(p!=NULL);
strcpy(p,"hello");
//free(p)
}
int main(void){
char* p = NULL;
fun(p);
printf("p=%s\n",p);
}
執行結果中並未輸出字符串hello其實這裏主函數調用fun函數,形參向實參傳遞參數的時候,發生的是拷貝。在fun函數中對局部指針變量p的任何修改都不會影響到主函數中的指針變量p。
值傳遞,形參的修改不會影響到實參
指針的地址傳遞
由於實參是一個一級指針的地址,要傳入這樣的地址給形參,這需要一個對應類型的二級指針來接受一級指針的地址。
//test.c
#include <cstdio>
#include <cstring>
#include <cassert>
void fun(char** p){
*p = (char*)malloc(sizeof(char)*100);
assert(*p != NULL);
strcpy(*p,"hello");
}
int main(void){
char* p = NULL;
fun(&p);
printf("p=%s\n",p);
free(p);
return 0;
}
指針的地址傳遞經常用在沒有頭節點的鏈表中,因爲在創建和銷燬鏈表時,頭指針的值需要被修改。如果用一級指針接收發生的是值傳遞,要修改其值必須用二級指針接收一級指針的地址,在這個地址對應的內存塊進行修改。
指針的引用傳遞
用二級指針操作一級指針的內存往往讓人難以理解,甚至往往還會發生內存泄漏的風險,在C++中,可以通過指針的引用簡化這樣的內存模型,實際上在編譯器內部還是處理爲二級指針,當使用時,解引用爲一級指針,如對無頭結點鏈表的初始化、銷燬等操作,也可以使用一級指針的引用簡化問題的處理
//test.cpp
#include <iostream>
using namespace std;
void fun(char* &p){
p = new char[100];
strcpy(p,"hello");
}
int main(){
char* p=NULL;
fun(p);
cout<<"p = "<<p<<endl;
delete [] p;
return 0;
}
理解一級指針的引用傳遞,編譯器在內存中開闢了臨時量,用於存儲引用變量的地址,一但使用引用變量就進行解引用。所以在外部看來,似乎就是使用了原變量 。