?
原始問(wèn)題
? ? ? 實(shí)現(xiàn)二叉樹排序,需要使用一個(gè)數(shù)組構(gòu)建一個(gè)二叉排序樹,最開(kāi)始寫的代碼如下:
struct
BST{
int
number;
//
保存數(shù)組元素的值
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]);
}
? ? ? 結(jié)果發(fā)現(xiàn)每次進(jìn)入insertBST的時(shí)候,tree指針都是空的。用簡(jiǎn)單的例子做實(shí)驗(yàn),發(fā)現(xiàn)如果一個(gè)指針為NULL,那么在函數(shù)中指向一個(gè)對(duì)象,函數(shù)返回后指針依舊為空,即函數(shù)中更改指針指向的對(duì)象無(wú)效。
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 <<
"
"
;
}
? ? ? 運(yùn)行上述代碼,發(fā)現(xiàn)輸出“b is null”,即b指針在tmp函數(shù)中被賦值無(wú)效。
? ? ? 而如果b指針預(yù)先執(zhí)行一個(gè)對(duì)象,那在tmp函數(shù)中改變其值是有效的。即在int*b = NULL下邊加上一行b=new int;的代碼,可以輸出改變后值為100.
?
? ? ? 如果希望在函數(shù)中為指針復(fù)制,可以使用額外一層的指針,具體代碼如下:
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 <<
"
"
;
}
此時(shí)可以輸出200.
?
問(wèn)題分析
? ? ? 為NULL的指針在函數(shù)中指向一個(gè)對(duì)象無(wú)效。而初始化之后可以改變指向?qū)ο蟮闹怠?
? ? ? 指針本身也是一個(gè)值,它的值是所指向?qū)ο蟮牡刂贰? 指針傳遞參數(shù)本質(zhì)上是值傳遞的方式,它所傳遞的是一個(gè)地址值。值 傳遞過(guò)程中,被調(diào)函數(shù)的形式參數(shù)作為被調(diào)函數(shù)的局部變量處理,即 在棧中開(kāi)辟了內(nèi)存空間以存放由主調(diào)函數(shù)放進(jìn)來(lái)的實(shí)參的值,從而成 為了實(shí)參的一個(gè)副本。值傳遞的特點(diǎn)是被調(diào)函數(shù)對(duì)形式參數(shù)的任何操 作都是作為局部變量進(jìn)行,不會(huì)影響主調(diào)函數(shù)的實(shí)參變量的值。
? ? ? 回到上述例子上,指針在傳遞時(shí),相當(dāng)于,在被調(diào)函數(shù)中,申明了一個(gè)int*的變量,其值就是傳遞進(jìn)來(lái)的int*.即調(diào)用tmp(b)時(shí),會(huì)執(zhí)行?int* c=int*b;?那么在被調(diào)函數(shù)的堆棧中修改局部變量int*c是 當(dāng)然也是不會(huì)影響到int*b的地址。
? ? ? 但是當(dāng)b指針不為NULL的時(shí)候,改變b指針的值會(huì)有效,這是因?yàn)榫植孔兞縞和參數(shù)b指向的是同一個(gè)對(duì)象,針對(duì)這個(gè)地址的修改在函數(shù)返回式依然有效。
?
解決方法
? ? ? 雙重星號(hào)的方式是有效的。
? ? ? 此時(shí)傳遞的不再是b指針的值,而是通過(guò)&b傳遞的b指針的地址,此時(shí)是參數(shù)是引用傳遞的,引用傳遞過(guò)程中,被調(diào)函數(shù)的形式參數(shù)雖然也作為局部變量在棧 中開(kāi)辟了內(nèi)存空間,但是這時(shí)存放的是由主調(diào)函數(shù)放進(jìn)來(lái)的實(shí)參變量 的地址。被調(diào) 函數(shù)對(duì)形參的任何操作都被處理成間接尋址,即通過(guò)棧 中存放的地址訪問(wèn)主調(diào)函數(shù)中的實(shí)參變量。正因?yàn)槿绱耍徽{(diào)函數(shù)對(duì) 形參做的任何操作都影響了主調(diào)函數(shù)中的實(shí)參變量。因此可以在函數(shù)中改變b指針的值,也就是指針指向的對(duì)象。
?
? ? ? 可以看出,對(duì)指針取地址,函數(shù)定義的時(shí)候使用雙重星號(hào)的作用不僅僅是為指針賦初始值,還可以在函數(shù)中改變指針指向哪個(gè)對(duì)象,而在普通的指針參數(shù)傳遞中,函數(shù)只能改變指針指向?qū)ο蟮闹担荒芨淖冎羔樉唧w指向哪個(gè)對(duì)象。
?
? ? ? 說(shuō)到底,出現(xiàn)該問(wèn)題的原因還是對(duì)指針的理解以及對(duì)參數(shù)傳遞方式的理解不夠到位。
?
? ? ? 完整的二叉樹排序代碼見(jiàn)上一篇博客: http://www.cnblogs.com/zhaoshuai1215/p/3448154.html
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

