2014-06-23 36 views
1

我想了解C++中尾部調用優化的含義。考慮下面的代碼段:局部變量和尾部調用優化

#include <iostream> 
#include <string> 

size_t mystrlen(const char* input, size_t size = 0){ 
    if(!*input){ 
     return size; 
    }else{ 
     std::string str(input+1); 
     return mystrlen(str.c_str(),size + 1); 
    } 
} 

int main(void){ 
    std::cout << mystrlen("Foo") << std::endl; //3 
} 

mystrlen爲(無用)函數,用於計算所提供的C字符串的長度。考慮else分支:創建一個新的std::string實例,並將其內部緩衝區用作下一個調用的輸入。如果發生尾部調用優化,並且沒有創建新的堆棧幀,是否會導致錯誤,因爲在下一次調用發生之前本地變量str將被銷燬?

+1

在這種情況下,尾部調用優化不會發生,因爲析構函數需要在返回後調用。 – Simple

+0

我的猜測是(基於直覺和邏輯結論),如果非POD對象的生命週期包含遞歸返回語句(即它在之前被構造,在返回之後被析構),那麼尾部調用優化是不可能的,因爲對於每個遞歸另一個對象生活。因此,所有這些對象都需要空間... [除非編譯器能夠檢測到該對象根本不需要,就像在此代碼中一樣;]] – leemes

+1

不要依賴尾部優化來避免堆棧溢出你的代碼。 –

回答

2

尾部調用優化在C++屬於C++編譯器擁有的as-if優化自由。

如果在高層次上對std::string非常詳細的知識進行編譯,那麼所做的操作將阻止尾部調用優化,因爲在遞歸調用完成後需要調用非平凡的析構函數。

0

首先,你要在這種情況下襬脫std::string

size_t mystrlen(const char* input, size_t size = 0) { 
    if(!*input){ 
     return size; 
    } else { 
     return mystrlen(input + 1, size + 1); 
    } 
} 

那麼你就可以看到你的尾巴調用優化將只是:

size_t mystrlen(const char* input) { 
    size_t size = 0; 
    while (!*(input + size)) ++size; 
    return size; 
} 
+0

我故意使用'std :: string'實例,因爲我想知道本地(非平凡)變量如何影響尾部調用優化的結果。否則我就不會寫這樣的功能;) – muffel