1. 程式人生 > >c/c++向函式傳遞指標並修改其指向的問題

c/c++向函式傳遞指標並修改其指向的問題

一個用來交換兩個數的值的函式,眾所周知的錯誤寫法為:

#include <iostream>
using namespace std;

void swap(int a, int b)
{
    int t = a;
    a = b;
    b = t;
}

int main()
{
    int a, b;
    cin >> a >> b;
    swap(a, b);
    cout<< a << " "<< b;
}

因為向函式中傳遞的只是a和b的拷貝,在函式執行結束後其中的a和b的值會被釋放,並不會影響呼叫者中a和b原有的值(即值傳遞的方法)。

一種正確的寫法為:

#include <iostream>
using namespace std;

void swap(int *p1, int *p2)
{
    int p;
    p = *p1;
    *p1 = *p2;
    *p2 = p;
    
}

int main()
{
    int a, b;
    int *p, *q;
    cin >> a >> b;
    p = &a;
    q = &b;
    
    swap(p, q);
    cout<< a << " "<< b;
}

這裡由於使用了指標傳遞,具體過程為:

函式執行前:


函式執行後:
可以看到,該種方法向函式傳遞了指向a和b的兩個指標,通過直接改變值a和b所在地址中的值的方法達到了交換值的目的。 但該種方法並未改變指標的指向。 而如果想要通過改變指標指向的方法來達到交換值的目的,一種想法是把swap函式修改為:
void swap(int *p1, int *p2)
{
    int *p;
    p = p1;
    p1 = p2;
    p2 = p;
}

方法看似很正確,但是很遺憾,執行完swap函式後a和b的值其實並沒有更改。 這是因為swap函式在接受兩個指標作為引數時,會為兩個指標p q建立一份形參拷貝即p1 q1。 函式執行前:

函式執行後:
可以看到,swap函式只改變了兩個形參的指向,並未對呼叫者的指標p q造成影響,這與第一種值傳遞的方法其實是一樣的,只不過這裡改變的是指標的值(即指標記憶體儲的地址的值)。 而如果想要在函式內修改指標的指向,並同時影響到呼叫者的指標,應該向函式傳遞二級指標(指標的指標):
#include <iostream>
using namespace std;

void swap(int **p1, int **p2)
{
    int *p;
    p = *p1;
    *p1 = *p2;
    *p2 = p;
}

int main()
{
    int a, b;
    int *p, *q;
    cin >> a >> b;
    p = &a;
    q = &b;
    
    swap(&p, &q);
    cout<< *p << " "<< *q;
}


這裡向函式傳遞了p q兩個指標的地址, swap函式用兩個二級指標形參p1 p2來接收。 函式執行前:
函式執行後:
在該函式中,進行交換的為*p1和*p2,即p和q中的值,也就是a和b兩個整數的地址。達到了修改指標的指向從而交換值的目的。 例子非常簡單易懂,但值得反思的是,在使用指標時一定要小心謹慎。尤其是不能被平時使用指標的思維慣性影響,以為向函式傳了指標,在函式內進行修改時,呼叫者的值就一定會被修改,要真正理解傳遞進函式的形參是誰,修改的值又是誰。