?
原始問題
? ? ? 實現二叉樹排序,需要使用一個數組構建一個二叉排序樹,最開始寫的代碼如下:
struct BST{ int number; // 保存數組元素的值 struct BST* left; struct BST* right; }; void insertBST(BST* tree, int v) { if (tree == NULL) { tree = new BST; tree ->left=tree->right= NULL; tree ->number= v; return ; } if (v < tree-> number) insertBST(tree -> left, v); else insertBST(tree -> right, v); } void createBST(BST* tree, int a[], int n) { tree = NULL; for ( int i= 0 ; i<n; i++ ) insertBST(tree, a[i]); }
? ? ? 結果發現每次進入insertBST的時候,tree指針都是空的。用簡單的例子做實驗,發現如果一個指針為NULL,那么在函數中指向一個對象,函數返回后指針依舊為空,即函數中更改指針指向的對象無效。
void tmp( int * a) { if (a== NULL) { a = new int ; *a= 200 ; } else *a= 100 ; } int main() { int * b= NULL; tmp(b); if (b == NULL) cout << " b is null " ; else cout << *b << " " ; }
? ? ? 運行上述代碼,發現輸出“b is null”,即b指針在tmp函數中被賦值無效。
? ? ? 而如果b指針預先執行一個對象,那在tmp函數中改變其值是有效的。即在int*b = NULL下邊加上一行b=new int;的代碼,可以輸出改變后值為100.
?
? ? ? 如果希望在函數中為指針復制,可以使用額外一層的指針,具體代碼如下:
void tmp( int ** a) { if (*a== NULL) { *a= new int ; **a= 200 ; } else **a= 100 ; } int main() { int * b= NULL; tmp( & b); if (b == NULL) cout << " b is null " ; else cout << *b << " " ; }
此時可以輸出200.
?
問題分析
? ? ? 為NULL的指針在函數中指向一個對象無效。而初始化之后可以改變指向對象的值。
? ? ? 指針本身也是一個值,它的值是所指向對象的地址。 指針傳遞參數本質上是值傳遞的方式,它所傳遞的是一個地址值。值 傳遞過程中,被調函數的形式參數作為被調函數的局部變量處理,即 在棧中開辟了內存空間以存放由主調函數放進來的實參的值,從而成 為了實參的一個副本。值傳遞的特點是被調函數對形式參數的任何操 作都是作為局部變量進行,不會影響主調函數的實參變量的值。
? ? ? 回到上述例子上,指針在傳遞時,相當于,在被調函數中,申明了一個int*的變量,其值就是傳遞進來的int*.即調用tmp(b)時,會執行?int* c=int*b;?那么在被調函數的堆棧中修改局部變量int*c是 當然也是不會影響到int*b的地址。
? ? ? 但是當b指針不為NULL的時候,改變b指針的值會有效,這是因為局部變量c和參數b指向的是同一個對象,針對這個地址的修改在函數返回式依然有效。
?
解決方法
? ? ? 雙重星號的方式是有效的。
? ? ? 此時傳遞的不再是b指針的值,而是通過&b傳遞的b指針的地址,此時是參數是引用傳遞的,引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在棧 中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量 的地址。被調 函數對形參的任何操作都被處理成間接尋址,即通過棧 中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對 形參做的任何操作都影響了主調函數中的實參變量。因此可以在函數中改變b指針的值,也就是指針指向的對象。
?
? ? ? 可以看出,對指針取地址,函數定義的時候使用雙重星號的作用不僅僅是為指針賦初始值,還可以在函數中改變指針指向哪個對象,而在普通的指針參數傳遞中,函數只能改變指針指向對象的值,不能改變指針具體指向哪個對象。
?
? ? ? 說到底,出現該問題的原因還是對指針的理解以及對參數傳遞方式的理解不夠到位。
?
? ? ? 完整的二叉樹排序代碼見上一篇博客: http://www.cnblogs.com/zhaoshuai1215/p/3448154.html
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
