7

私はObjectiveC++プロジェクトを持っています。 ObjectiveCコンテキストではARCとiPhoneSDK 6を使用しています.C++ではC++ 11コンパイラを使用しています。ARC ObjectiveC++でC++ 11ラムダ関数を使用する方法 - 正しく行うには?

C++ 11でのLambda関数は、参照で変数を取り込みます。この概念はObjectiveCでは実際にはサポートされておらず、「試行錯誤」で私は以下の解決策を考え出しました。私が気づいていない落とし穴がありますか?

この問題の解決策がありますか?

typedef std::function<void()> MyLambdaType; 

... 
// m_myView will not go away. ARC managed. 
UIView * __strong m_myView; 

... 
// In Objective C context I create a lambda function that calls my Objective C object 
UIView &myViewReference = *m_myView; 
MyLambdaType myLambda = [&myViewReference]() { 
    UIView *myViewBlockScope = &myViewReference; 
    // Do something with `myViewBlockScope` 
} 

.. 
// In C++11 context I call this lambda function 
myLambda(); 
+0

なぜブロックを使用しないのですか? – kennytm

+0

AFAIKブロックはObjectiveCのみ、または?どのようにブロックをC++に渡すのですか? –

+0

'MyLambdaType myLambda = [m_myView](){// m_myViewで何かする}'は動作しませんか? – newacct

答えて

12

行うには簡単な事は(私はこれがローカル変数であることを、あなたのスニペットから想定しています)ラムダは、オブジェクトのポインタ変数m_myViewをキャプチャできるようにすること、およびラムダ内で正常にそれを使用します。

MyLambdaType myLambda = [m_myView]() { 
    // Do something with `m_myView` 
} 

唯一の懸念は、m_myViewのメモリ管理です。一般に正しいように、ラムダは作成時にm_myViewを保持し、破壊されたときに解放する必要があります(ブロックのようにラムダはm_myViewが存在しないスコープで使用できるため)。

ARCドキュメントを読むと、具体的に言及されているこの状況はありませんが、(1)C++ 11ラムダのキャプチャされた変数が匿名のフィールドとして格納されているため(2)ARCは、構築と破壊に関するC++クラスのObjective-Cオブジェクトフィールドの保持と解放を適切に処理します。ラムダとは逆の言い方、あるいはコンパイラのバグがない限り、私はそれがうまくいかない理由は見当たりません。

+4

これは間違いなく動作します。トリッキーなことは、C++ 11ラムダの用語では、「m_myView」がここでは「値によって」キャプチャされているということです。 "[&m_myView](){...}')のように "参照によって"それを取得した場合、オブジェクトm_myViewはARCによって保持されません。これについて考えるなら、これは完璧な意味があります(つまり、C++に参照によって 'm_myView'をキャプチャするよう指示すると、C++はオブジェクトへの参照ではなくポインタ*への参照をキャプチャしています)。しかし、用語は少し混乱します。 – ipmcc

+0

@ipmcc:はい。これは、一般的なC++ 11ラムダでの参照によるキャプチャに当てはまります。 C++ 11のラムダで参照によって取得する場合、キャプチャされた変数の範囲外でそのラムダを使用することはできません。 – newacct

+0

m_myViewで使用されているメモリがARCによって解放されていないようです。私はコードで数ミリ秒ごとにたくさんのコールバックを取得しています。私の記憶は着実に飛び跳ねています。ラムダ関数内で作成されたObjective-Cオブジェクトでも同じです。彼らはまた漏れている。 –

関連する問題