【C++】對於指針參數在函數體內改變指向,爲何從函數出來之後並沒有改變?

背景:

最近剛開始自學數據結構,大學學的實在是雲裏霧裏的,想着自己用C++實現一下僞代碼吧,大概思路是這樣的:

在main裏定義了一個SqList *L = NULL;

在InitList(SqList *L);函數裏new出來一塊內存分配給L:

  L = new SqList();

因爲L是在main裏定義的,按照我所預想的,在初始化函數裏分配了內存塊就OK了,因爲指針傳參傳遞的是地址,所以L肯定被改變了。

但是事實是,一旦退出了InitList之後,L的地址就回歸到了坑爹的全0


我通過指針傳遞參數,並試圖在函數體內改變指針,但是發現這只是改變了函數體內的指針,函數結束後,main裏的指針還是任爾東南西北風我自巋然不動j_0016.gif


一、 你所傳遞和改變的到底是什麼

爲什麼會這樣呢?明明我以前做指針傳參的話,值都改變了啊(你大概會這麼想)

廢話不多說,百思不得其解的時候可以通過一個小demo測試一下


#include <iostream>
using namespace std;
void changePointer(int *p)
{
    p = new int(1);
    cout << "p in = " << p << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int *p =new int(0);
    cout << "p1 = " << p << endl;
    changePointer(p);
    cout << "p2 = " << p << endl;
    return 0;
}

這個結果很坑爹的驗證了之前的問題:

wKiom1NTg4DwyVSIAAAnFyBKUYE850.jpg

看到沒有?

p在經過changePointer之後並沒有改變其地址,問題就在這裏:

我們平常是用指針傳遞參數,然後在函數體裏改變指針保存的地址所存儲的值,而不是改變指針所保存的地址,這裏很多人都會偷換了概念

好吧,有一點繞口,上代碼,仔細考慮一下以下兩行代碼的區別:

*p = 1; // p並沒有被改變,但是p所指向的值被改變了
p = new int(1); // p被改變了


是不是不一樣?好了,知道了爲什麼這個跟平時自己用的指針傳參不一樣之後,讓我們考慮一下,是什麼導致了p在函數體內被改變了,出了函數體就變回來了呢?


二、指針參數究竟是如何傳遞的

記得之前看過一個關於參數傳遞的文章,具體的不記得,大概有臨時變量這麼一說,既然是臨時的,會不會出函數就over了,所以就導致了main中的p未被改變?

記憶總是模糊的,我們可以問度娘

事實證明確實是這樣的

問過度娘之後,得到這麼一句話:

編譯器總是要爲函數的每個參數製作臨時副本,指針參數p的副本是 _p,編譯器使 _p = p。如果函數體內的程序修改了_p的內容,就導致參數p的內容作相應的修改。這就是指針可以用作輸出參數的原因

而如果我們修改的是_p保存的地址,而非_p地址指向的值,那麼函數結束之後,臨時變量被修改和p有毛關係呢


三、怎麼樣才能達到我們的預期目的——改變指針


1. 比較簡單的一種是:返回值

直接把在函數體裏new出來的返回就好了嘛~~~

檢驗一下:

int* changePointer(int *p)
{
    p = new int(1);
    cout << "p in = " << p << endl;
    return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int *p =new int(0);
    cout << "p1 = " << p << endl;
    p = changePointer(p);
    cout << "p2 = " << p << endl;
    return 0;
}

輸出:

wKiom1NTgAPyhDTJAAAiIhVKHzo202.jpg

Good job~!你妹的指針終於被改了有木有~~~


2. 指針的指針

void changePointer(int **p)
{
    *p = new int(1);
    cout << "p in = " << *p << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int *p =new int(0);
    cout << "p1 = " << p << endl;
    changePointer(&p);    // 注意這裏傳遞的是&p
    cout << "p2 = " << p << endl;
    return 0;
}

輸出:

wKioL1NTgOHw1cXlAAAicBKdoA4394.jpg


作爲一個渣渣,C++慢慢摳語法摳底層真的很辛苦,成爲大神之路任重而道遠

幹吧呆,小夥伴們

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章