2016-10-27 9 views
1

私はVS2013を使用していて、lambdaを含むクラスのインスタンスを複数使用しているときに奇妙な動作をしていることを発見しました。静的変数は共有されているように見えます。C++ラムダと静的変数の予想される動作

例コード、非常に多くのトリムダウンが、まだ本質を捉え:

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; 
} 

私が手に出力されます。value同じになるように:

a: 7 
b: 42 
a: 42 

私は2番目期待しているだろう最初の人として。私はコンパイラのバグを見ていますか?あるいは、ラムダと静的変数の働きを誤解していますか?私はラムダを何らかの方法で間違って使用していますか?

答えて

5

ラムダは、必要なときに作成されるオブジェクトではありませんが、クラスのインライン定義の省略形です。そこ

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は基本的に名前が付けられていません。彼らのタイプに名前を付ける方法はないので、auto変数や、オブジェクトのような関数を格納するのがうれしいstd :: functionのようなものに代入するのではなく、多くのことをすることはできません。 – Charlie

関連する問題