2014-05-06 3 views
7

मुझे पता है कि कब्जा सूचियों तो जैसे चर उपलब्ध बनाने एक लैम्ब्डा समारोह शरीर के अंदर:लैम्बडास की कैप्चर सूचियां वास्तव में सी ++ 11 में कैसे काम करती हैं?

int pos(0); 
std::function<void()> incPos = [&pos](){ ++pos; }; 
incPos(); //pos is now 1 

लेकिन यह कैसे है कि वास्तव में संकलक स्तर पर काम पर कब्जा करता है? कैप्चर किए गए पते या कैप्चर किए गए मान कहां संग्रहीत किए जाते हैं?

+1

लैम्बडास अनिवार्य रूप से [functors] (http://en.wikipedia.org/wiki/Function_object) हैं जिन्हें आपको स्वयं लिखना नहीं है। –

उत्तर

9

प्रत्येक लैम्ब्डा अभिव्यक्ति एक अद्वितीय फ़ंक्शन ऑब्जेक्ट (बंद) उत्पन्न करती है जो कैप्चर किए गए चर को डेटा सदस्यों के रूप में संग्रहीत करती है। उदाहरण के लिए, अपने कोड में लैम्ब्डा अभिव्यक्ति संकलक द्वारा कुछ इस तरह के रूप में तब्दील किया जाएगा:

struct __uniquely_named_lambda 
{ 
    __uniquely_named_lambda(int& pos) 
    : pos(pos) {} 
    int& pos; 

    void operator()() const 
    { ++pos; } 
}; 

लैम्ब्डा लागू बस operator() के लिए एक कॉल है।

डेटा सदस्य संदर्भ से कब्जा करने के बाद से एक संदर्भ है। यदि आप मूल्य से कब्जा कर लिया है तो यह एक सादा int होगा। यह भी ध्यान रखें कि उत्पन्न operator() डिफ़ॉल्ट रूप से const है। यही कारण है कि आप कब्जे वाले चर को संशोधित नहीं कर सकते हैं जब तक कि आप mutable कीवर्ड का उपयोग न करें।

+0

नोट, हालांकि, उपरोक्त ** ** नहीं है ** बिल्कुल क्या होता है। जादू के लिए 'लूप' के विपरीत और अधिकांश सी ++ की तरह, यह व्यवहार है जो मानकीकृत है, और यह व्यवहार सी ++ कोड में एन्कोड नहीं किया गया है। विशेष रूप से, उपरोक्त "नकली" लैम्ब्डा में एक कन्स्ट्रक्टर होता है - भेड़ के बच्चे को स्वयं की आवश्यकता नहीं होती है (वे जादू के माध्यम से इसे कर सकते हैं)। इसके अतिरिक्त, यदि आप ऊपर दिए गए "नकली" लैम्ब्डा को एक संदर्भ पास करते हैं, तो यह तब तक मान्य रहता है जब संदर्भित डेटा मान्य होता है - वास्तविक लैम्ब्डा तकनीकी रूप से डेटा ** और ** दोनों संदर्भ चर के लिए मान्य रहता है। – Yakk

+1

@Yakk: जैसा कि नियम के तहत, कंप्यूटर्स को हमेशा C++ को लागू करने की आजादी होती है जब तक कि _observable व्यवहार_ समान न हो। रचनाकारों का अस्तित्व देखने योग्य नहीं है। – MSalters

+0

@msalters प्रकार कटौती का उपयोग करें कक्षाओं का गुण। उनमें से कुछ कन्स्ट्रक्टर अस्तित्व के आधार पर भिन्न हैं। फ़ंक्शन ओवरलोड (फिर से, टाइप कटौती के माध्यम से टाइप करें) के माध्यम से गैर-स्पष्ट यूनरी सीटीआर का पता लगाया जा सकता है (फिर भी अगर निजी हो), लेकिन निश्चित नहीं है कि मैं स्पष्ट या बहु तर्क (thinkimg '{}' ओवरलोड के साथ निर्माण के साथ ऐसा कर सकता हूं?) - मुझे विश्वास नहीं है कि यह देखने योग्य नहीं है, लेकिन निश्चित नहीं है। – Yakk

संबंधित मुद्दे