2016-10-27 25 views
1

我正在使用VS2013,並發現當使用包含lambda表達式的類的多個實例並且這些lambda表達式包含靜態變量時,在我看來是奇怪的行爲。靜態變量似乎是共享的。C++ lambda表達式和靜態變量的預期行爲

示例代碼,非常下調,但仍然抓住了精髓:

class HasLambda 
{ 
public: 
    typedef const char* (*ToCharPtr) (const int&); 
    void Init(ToCharPtr pfnToCharPtr) { 
     m_pfnCharPtrConverter = pfnToCharPtr; 
    } 

    const char* IntToString(int i) { 
     return m_pfnCharPtrConverter(i); 
    } 

    static HasLambda* Make() { 
     HasLambda* pHasLambda = new HasLambda; 
     pHasLambda->Init([] (const int &i) -> const char* { static char buf[ 33 ]; sprintf(buf, "%d", i); return buf; }); 
     return pHasLambda; 
    } 

protected: 
    ToCharPtr m_pfnCharPtrConverter; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HasLambda* a; 
    a = HasLambda::Make(); 

    HasLambda* b; 
    b = HasLambda::Make(); 

    const char* aValue = a->IntToString(7); 
    printf("a: %s\n", aValue); 

    const char* bValue = b->IntToString(42); 
    printf("b: %s\n", bValue); 
    printf("a: %s\n", aValue); 

    return 0; 
} 

我得到的輸出是:

a: 7 
b: 42 
a: 42 

我本來期望第二個是:值是相同的作爲第一個。我看到編譯器錯誤,還是誤解了其中的lambda表達式和靜態變量的工作方式?我是否以某種方式使用lambda錯誤?

回答

5

lambda不是在需要時創建的對象,而是類的內聯定義的簡寫。你上面的調用將大致相當於:

class SomeLambda { 
public: 
    const char* operator() (const int& i) { 
    static char buf[33]; 
    sprintf(buf, "%d", i); 
    return buf; 
    } 
}; 

... 
pHasLambda->Init(SomeLambda()); 

靜態初始化規則存在的含義任何功能級別的靜態成員函數調用相同。

如果不是有兩個不同的線路創建拉姆達例如:

auto x = []() { static char buf[99]; use_buf(buf); return buf; }; 
auto y = []() { static char buf[99]; use_buf(buf); return buf; }; 

那麼x和y是獨立的類,儘管有相同的定義。

+0

我明白你的意思了。 – Rodyland

+0

是'SomeLambda'是'HasLambda'的內部類?如果是這樣,我猜它是私人的? –

+1

sfk92fksdf @ Lambdas基本上是未命名的。沒有辦法爲它們的類型命名,所以除了將它們分配給自動變量或像std :: function這樣的存儲任何函數(比如對象)的東西外,你無法用它們做很多事情。 – Charlie