C++二級指針和指針引用傳參


前提

一級指針和引用

已經清晰一級指針和引用。
可參考:指針和引用與及指針常量和常量指針 或查閱其他資料。

一級指針和二級指針

個人覺得文字描述比較難讀懂,直接看代碼運行結果分析好些,如果想看文字分析,可參考文末參考文章。

例子

#include <iostream>
using namespace std;
int main()
{
     int a=5;
     int *q=&a;
     int **pp=&q;
     //下面的兩行輸出在垂直方向上的相應值相同,由輸出可知一級指針和二級指針的關系。
     cout<<pp<<" "<<*pp<<" "<<*&pp<<" "<<**pp<<endl;
     cout<<&q<<" "<< q <<" "<< &q <<" "<< *q <<endl;
     return 0;
}

運行結果:

二級指針傳參

#include <iostream>
using namespace std;

void make(int **pp)
{
    **pp = 66;//這樣只是改變了指向的值,即a, 指向沒有改變
}
int main()
{
     int a=5;
     int *q=&a;
     int **pp=&q;
     cout<<"address:"<<&pp<<"  "<<pp<<"    "<<&q<<"   "<<q<<"      value:"<<*q<<"  "<<a<<endl;
     make(pp);
     cout<<"address:"<<&pp<<"  "<<pp<<"    "<<&q<<"   "<<q<<"      value:"<<*q<<"  "<<a<<endl;
     return 0;
}

運行結果:

如果改為:

#include <iostream>
using namespace std;

void make(int **pp)
{
   int * p=new int(66);
   *pp=p; //這樣便使用函數通過二級指針傳參更改了一級指針的指向(值便也改了),但原指向的值不變。其實這和使用一級指針傳參改變其指向的值類似,只不過多加了一級指針。
}
int main()
{
     int a=5;
     int *q=&a;
     int **pp=&q;
     cout<<"address:"<<&pp<<"  "<<pp<<"    "<<&q<<"   "<<q<<"       value:"<<*q<<"  "<<a<<endl;
     make(pp);
     cout<<"address:"<<&pp<<"  "<<pp<<"    "<<&q<<"   "<<q<<"       value:"<<*q<<"  "<<a<<endl;
}

運行結果:


指針引用傳參

例子

#include<iostream>
using namespace std;

void make(int *pp)
{
    pp=new int(66); //試圖改變p指向的地址,但沒有用,看運行結果。
}
int main()
{
    int a=5;
    int *p=&a; //指針變量指向一個int類型的地址
    cout<<"address:"<<&a<<"       value:"<<a<<endl;
    cout<<"address:"<<p<<"       value:"<<*p<<endl;
    make(p);
    cout<<"address:"<<p<<"       value:"<<*p<<endl;
}

運行結果:

這里pp只是p的一個拷貝,pp在函數中相當於一個局部變量。

指針傳遞參數本質上是值傳遞的方式,它所傳遞的是一個地址值。
值傳遞過程中,被調函數的形式參數作為被調函數的局部變量處理,即在棧中開辟了內存空間以存放由主調函數放進來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調函數對形式參數的任何操作都是作為局部變量進行,不會影響主調函數的實參變量的值。
源自:C++中引用,指針,指針的引用,指針的指針

更改為:

#include<iostream>
using namespace std;

void make(int *&pp)
{
    pp=new int(66); //此時pp相當於p的別名,所以改的就是指針p本身,所以更改成功。
}
int main()
{
    int a=5;
    int *p=&a; //指針變量指向一個int類型的地址
    cout<<"address:"<<&a<<"       value:"<<a<<endl;
    cout<<"address:"<<p<<"       value:"<<*p<<endl;
    make(p);
    cout<<"address:"<<p<<"       value:"<<*p<<endl;
}

運行結果:

其實這里pp也是主調函數中p一個拷貝,但不同的是:任何對於引用參數的處理都會通過一個間接尋址的方式操作到主調函數中的相關變量,所以最終是對於實參的操作。

再多說一點

引用傳參與指針傳參的不同還在於:指針傳遞參數時,指針中存放的也是實參的地址,但是在被調函數內部指針存放的內容可以被改變,即可能改變指向的實參,所以並不安全,而引用則不同,它引用的對象的地址一旦賦予,則不能改變。這也正是引用的初衷。

參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM