2012-07-22 6 views
24

नीचे दिए गए कोड 0 को प्रिंट करते हैं, लेकिन मुझे 1 देखने की उम्मीद है। मेरा निष्कर्ष यह है कि लैम्ब्डा फ़ंक्शंस वास्तव में फ़ंक्शंस में कैप्चर पैरामीटर पास करके नहीं आते हैं, जो अधिक है सहज ज्ञान युक्त। क्या मैं सही हूँ या क्या मुझे कुछ याद आ रहा है?सी ++ 11 लैम्ब्डा कैप्चर घोषणा मूल्य पर कैप्चर द्वारा

#include <iostream> 
int main(int argc, char **argv){ 
    int value = 0; 
    auto incr_value = [&value]() { value++; }; 
    auto print_value = [ value]() { std::cout << value << std::endl; }; 
    incr_value(); 
    print_value(); 
    return 0; 
} 

उत्तर

23

Lambda प्रकार्य वास्तव में कार्य करने के लिए कब्जा कर लिया पैरामीटर प्रदान करने के द्वारा लाया जाता है।

value उस बिंदु पर 0 के बराबर है जहां लैम्ब्डा परिभाषित किया गया है (और value कैप्चर किया गया है)। चूंकि आप मूल्य से कैप्चरिंग कर रहे हैं, इससे कोई फर्क नहीं पड़ता कि आप कैप्चर करने के बाद value पर क्या करते हैं।

यदि आपने संदर्भ द्वारा value पर कब्जा कर लिया है, तो आपको एक मुद्रित दिखाई देगा क्योंकि भले ही कैप्चर का बिंदु अभी भी वही है (लैम्ब्डा परिभाषा) आप कब्जे वाले ऑब्जेक्ट का वर्तमान मूल्य प्रिंट करेंगे और प्रतिलिपि नहीं जब इसे कब्जा कर लिया गया था तब इसे बनाया गया था।

+0

धन्यवाद। मैं मूल्य के बारे में सोच रहा था क्योंकि मूल्य के अपडेट में फ़ंक्शन के बाहर दिखाई नहीं देगा। हालांकि, ऐसा लगता है जैसे फ़ंक्शन के बाहर के फ़ंक्शन फ़ंक्शन के अंदर दिखाई नहीं देंगे। – perreal

+6

यहां भ्रामक क्या हो सकता है शब्द है: मूल्य से "एक प्रति उत्पन्न करें"। लैम्ब्डा में परिवर्तनीय की एक प्रति है, यह लैम्ब्डा की घोषणा के बिंदु पर लिया गया मूल्य है। चूंकि लैम्ब्डा की निजी प्रतिलिपि होती है, मूल वस्तु को लैम्ब्डा के अंदर संशोधित या पढ़ा नहीं जाता है। यही कारण है कि वास्तव में संदर्भ द्वारा कैप्चर किया गया है, जिस स्थिति को आप मूल को देखना/संशोधित करना चाहते हैं। – Klaim

12

हां, लैम्ब्डा घोषित बिंदु पर कैप्चर किए जाते हैं, जब इसे बुलाया जाता है। एक लैम्ब्डा को फ़ंक्शन ऑब्जेक्ट के रूप में सोचें जिसका कन्स्ट्रक्टर कैप्चर किए गए वैरिएबल को पैरामीटर के रूप में लेता है और उन्हें कैप्चर मोड के आधार पर इसके संबंधित सदस्य चर (या तो मान या संदर्भों को निर्दिष्ट करता है।) लैम्ब्डा के वास्तविक कॉल में कोई जादू नहीं है, यह सिर्फ एक है अंतर्निहित फ़ंक्शन ऑब्जेक्ट का नियमित operator() कॉल।

कॉल पॉइंट पर चीजों को कैप्चर करना ज्यादा समझ में नहीं आता है - अगर लैम्ब्डा वापस लौटाया गया था या किसी अन्य फ़ंक्शन पर पैरामीटर के रूप में पारित किया गया था और वहां कहा जाता है तो क्या पकड़ा जाएगा? वास्तव में ऐसी भाषाएं हैं जो इस तरह से व्यवहार करती हैं - यदि आप किसी फ़ंक्शन में एक चर x का संदर्भ लेते हैं, तो यह वर्तमान में कॉल के बिंदु पर x नामक किसी भी चर को संदर्भित करता है। इसे गतिशील स्कॉइंग कहा जाता है। वैकल्पिक, अधिकांश भाषाओं द्वारा उपयोग किया जाता है क्योंकि यह प्रोग्रामों के बारे में तर्क को अधिक सरल बनाता है, जिसे लेक्सिकल स्कोपिंग कहा जाता है।

http://en.wikipedia.org/wiki/Lexical_scoping#Lexical_scoping_and_dynamic_scoping

5

समस्या यह है कि आपके प्रिंट समारोह मूल्य द्वारा और संदर्भ द्वारा नहीं पर कब्जा कर रहा है।

#include <iostream> 
int main(int argc, char **argv){ 
    int value = 0; 
    auto incr_value = [&value]() { value++; }; 
    auto print_value = [ value]() { std::cout << value << std::endl; }; 
    auto print_valueref = [ &value]() { std::cout << value << std::endl; }; 

    incr_value(); 
    print_value(); 
    print_valueref(); 
    return 0; 
} 

आउटपुट 0 और 1 अपेक्षित के रूप में। पहला व्यक्ति मूल्य से कब्जा कर लिया जाता है और कैप्चर के बिंदु पर मूल्य प्रिंट करता है; दूसरा संदर्भ संदर्भ को कैप्चर करता है और फिर उसके मूल्य को प्रिंट करता है।

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

  • कोई संबंधित समस्या नहीं^_^