函數(shù)調(diào)用會(huì)在內(nèi)存形成一個(gè)“調(diào)用記錄”襟沮,又稱“調(diào)用幀”(call frame)锥惋,保存調(diào)用位置和內(nèi)部變量等信息。如果在函數(shù)A的內(nèi)部調(diào)用函數(shù)B开伏,那么在A的調(diào)用幀上方膀跌,還會(huì)形成一個(gè)B的調(diào)用幀。等到B運(yùn)行結(jié)束固灵,將結(jié)果返回到A捅伤,B的調(diào)用幀才會(huì)消失。如果函數(shù)B內(nèi)部還調(diào)用函數(shù)C巫玻,那就還有一個(gè)C的調(diào)用幀暑认,以此類推。所有的調(diào)用幀大审,就形成一個(gè)“調(diào)用椪杭剩”(call stack)。
尾調(diào)用由于是函數(shù)的最后一步操作徒扶,所以不需要保留外層函數(shù)的調(diào)用幀粮彤,因?yàn)檎{(diào)用位置、內(nèi)部變量等信息都不會(huì)再用到了,只要直接用內(nèi)層函數(shù)的調(diào)用幀导坟,取代外層函數(shù)的調(diào)用幀就可以了屿良。
注意,只有不再用到外層函數(shù)的內(nèi)部變量惫周,內(nèi)層函數(shù)的調(diào)用幀才會(huì)取代外層函數(shù)的調(diào)用幀尘惧,否則就無(wú)法進(jìn)行“尾調(diào)用優(yōu)化”。
遞歸非常耗費(fèi)內(nèi)存递递,因?yàn)樾枰瑫r(shí)保存成千上百個(gè)調(diào)用幀喷橙,很容易發(fā)生“棧溢出”錯(cuò)誤(stack overflow)。但對(duì)于尾遞歸來(lái)說(shuō)登舞,由于只存在一個(gè)調(diào)用幀贰逾,所以永遠(yuǎn)不會(huì)發(fā)生“棧溢出”錯(cuò)誤。