7

मेरे पास एक ObjectiveC++ प्रोजेक्ट है। ऑब्जेक्टिव संदर्भ में मैं एआरसी और आईफोनएसडीके 6 का उपयोग कर रहा हूं। सी ++ में मैं एक सी ++ 11 कंपाइलर का उपयोग कर रहा हूं।एआरसी ऑब्जेक्टिव सी ++ में सी ++ 11 लैम्ब्डा फ़ंक्शंस का उपयोग करना - इसे ठीक से कैसे करें?

सी ++ 11 में लैम्ब्डा फ़ंक्शन संदर्भों के साथ चर कैप्चर कर रहे हैं। यह अवधारणा वास्तव में 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 ब्लॉक केवल उद्देश्य सी हैं, या? मैं सी ++ में ब्लॉक कैसे पास करूं? –

+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 मौजूद नहीं है)।

एआरसी दस्तावेज़ों के माध्यम से पढ़ना, मुझे यह स्थिति विशेष रूप से उल्लिखित नहीं दिखाई देती है, लेकिन मेरा मानना ​​है कि इसे ठीक से संभालना चाहिए, क्योंकि (1) एक सी ++ 11 लैम्ब्डा के कब्जे वाले चर को अज्ञात के फ़ील्ड के रूप में संग्रहीत किया जाता है कक्षा, जिसे लैम्ब्डा के निर्माण के दौरान कैप्चर किए गए मूल्य में प्रारंभ किया जाता है, और (2) एआरसी निर्माण और विनाश पर सी ++ कक्षाओं के उद्देश्य-सी ऑब्जेक्ट फ़ील्ड को बनाए रखने और जारी करने के लिए सही तरीके से संभालता है। जब तक यह विशेष रूप से लैम्बडास के विपरीत कुछ नहीं कहता है, या एक कंपाइलर बग है, तो मुझे कोई कारण नहीं दिखता कि इसे क्यों काम नहीं करना चाहिए।

+4

यह निश्चित रूप से काम करता है। मुश्किल बात यह है कि सी ++ 11 लैम्ब्डा शब्दावली में, 'm_myView' को "मूल्य से" कैद किया जा रहा है। यदि आप इसे "संदर्भ द्वारा" कैप्चर करते हैं (जैसे: '[& m_myView]() {...} ') ऑब्जेक्ट' m_myView' * एआरसी द्वारा बनाए रखा नहीं है। यदि आप इसके बारे में सोचते हैं, तो यह सही समझ में आता है (यानी जब आप संदर्भ द्वारा 'm_myView' को कैप्चर करने के लिए C++ को बताते हैं, तो C++ पॉइंटर * पर संदर्भ * कैप्चर कर रहा है, ऑब्जेक्ट का संदर्भ नहीं) लेकिन शब्दावली थोड़ा उलझन में हो सकती है । – ipmcc

+0

@ipmcc: हां। सामान्य रूप से सी ++ 11 लैम्बडास में संदर्भ द्वारा कैप्चरिंग के लिए यह सच है। यदि आप सी ++ 11 लैम्ब्डा में संदर्भ द्वारा कैप्चर करते हैं, तो आप उन कैप्चर चर के दायरे से बाहर उस लैम्ब्डा का उपयोग नहीं कर सकते हैं। – newacct

+0

ऐसा लगता है कि m_myView द्वारा उपयोग की गई स्मृति एआरसी द्वारा जारी नहीं की जाती है। मुझे अपने कोड में हर कुछ मिलीसेकंड्स में बहुत सारे कॉलबैक मिल रहे हैं और मेरी याददाश्त तेजी से कूद रही है। लैम्बडा फ़ंक्शन के अंदर बनाए गए उद्देश्य-सी ऑब्जेक्ट्स के लिए यह वही है। वे भी लीक कर रहे हैं। –