2013-02-28 40 views
1

如何在保持代碼的遞歸性質的同時使此函數線程安全?在保持遞歸性的同時使此函數保持安全線程

int foo(char *p) 
{ 
    static int i = 0; 
    if (*p == '\0') return i; 
    i++; 
return foo(p+1); 
} 
+3

通過'我'作爲第二個參數。但爲什麼??? – 2013-02-28 20:05:09

+0

可能會更精緻一點?謝謝。 – user2115365 2013-02-28 20:06:24

+0

[你稱之爲線程安全的東西是什麼 - Eric Lippert](http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call- thread-safe.aspx) – 2013-02-28 20:16:17

回答

5
#include <iostream> 

using namespace std; 

int foo(char* p, int start) 
{ 
    if (*p == 0) return start; 
    return foo(p+1, start+1); 
} 

int main() 
{ 
    char test[] = "HI THERE"; 

    cout << foo(test, 0); 

    return 0; 
} 
+0

這有額外的優勢,允許尾遞歸優化(即函數調用可以轉換爲循環) – 2013-02-28 20:16:36

+0

這不是等同的,雖然'我'得到重置每個電話。 – Pubby 2013-02-28 20:19:42

+1

@Pubby不等同,但可能是OP真正想要的。 :-) – 2013-02-28 20:38:23

3

在C++ 11,你可以使用thread_local

int foo(char *p) 
{ 
    thread_local int i = 0; 
    if (*p == '\0') return i; 
    i++; 
    return foo(p+1); 
} 

功能是,我希望,只是舉個例子作爲i=0將只執行一次(在你的例子)並在我的示例中每個線程一次

舊版編譯器有時支持將static __thread作爲C++之前的替代版本。

1
int foo(char *p, int i = 0) 
{ 
    if(*p == '\0') 
     return i; 
    return foo(p+1, i+1); 
} 

遞歸是很好,所有,但它可以低於循環,如果創建堆棧幀。這是導致堆棧溢出的最簡單方法。我會建議擺脫它。以下是簡單和容易更快:

int foo(char *p) 
{ 
    return strlen(p); 
} 

或者更好的是,只需撥打strlen直接擺脫foo

請注意,這是非常不安全的。如果'\0'不來?你只會讀到誰知道什麼......

+0

+1爲'i'的默認值。但'strlen'就像「不安全」一樣(除了它不會在超長字符串中堆棧)...... p參數指向NUL終止的字符串是一個(不可測試的)前提條件。 – 2013-02-28 20:31:32

+0

這將工作在通用庫嗎? – user2115365 2013-03-01 08:43:49

+0

@ user2115365'strlen'是一個通用的庫... C++標準庫。它的工作原理。 – David 2013-03-01 13:18:22