2016-06-05 5 views
12

मैं सी के माध्यम से पढ़ रहा हूँ द्वारा कब्जा this book के 3 अध्याय में लैम्ब्डा अनुभाग ++ और निम्नलिखित कोड मुझे confuses:C++ लैम्ब्डा मूल्य

int x = 0; 
int y = 42; 
auto qqq = [x, &y] { 
    std::cout << "x: " << x << std::endl; 
    std::cout << "y: " << y << std::endl; 
    ++y; 
}; 
x = y = 77; 
qqq(); 
qqq(); 
std::cout << "final y: " << y << std::endl; 

इस कोड को प्रिंट आउट:

x: 0 
y: 77 
x: 0 
y: 78 
final y: 79 

क्यों QQQ करता है() रजिस्टर नहीं है कि एक्स बदल गया है 77? यह कहा गया था कि मूल्य से गुजरने का मतलब है कि हम पढ़ सकते हैं लेकिन डेटा को पढ़ने योग्य नहीं संशोधित कर सकते हैं जहां लैम्ब्डा परिभाषित किया गया था। क्या इसका मतलब है कि हम इसकी परिभाषा के बाद परिवर्तन नहीं देख सकते हैं?

+0

आप सही हैं, वह पुस्तक बहुत अच्छी व्याख्या नहीं देती है। नीचे दिए गए उत्तर बेहतर काम करते हैं। – jdigital

उत्तर

14

ऐसा इसलिए है क्योंकि जब आप लैम्ब्डा को परिभाषित करते हैं तो वैरिएबल केवल एक बार मूल्य (यानी प्रतिलिपि) द्वारा कब्जा कर लिया जाता है। यह "अपडेट" नहीं है जैसा कि आप विश्वास कर सकते हैं। कोड के लिए मोटे तौर पर बराबर है:

#include <iostream> 

int x = 0; 
struct Lambda 
{ 
    int _internal_x; // this is used to "capture" x ONLY ONCE 
    Lambda(): _internal_x(x) {} // we "capture" it at construction, no updates after 
    void operator()() const 
    { 
     std::cout << _internal_x << std::endl; 
    } 
} qqq; 

int main() 
{ 
    qqq(); 
    x = 77; // this has no effect on the internal state of the lambda 
    qqq(); 
} 

Live on Coliru

4

लैम्ब्डा समय लैम्ब्डा परिभाषित किया गया है (यह एक प्रतिलिपि बनाता है) पर मान का उपयोग करता, समय पर शुरू हो जाती है नहीं।

यह मदद कर सकता है: How are Lambda Closures Implemented?

9

एक लैम्ब्डा बंद करने के लिए मूल्य द्वारा एक चर बाध्यकारी करके, आप प्रभावी रूप से एक अलग चर कि लैम्ब्डा ऑब्जेक्ट के अंदर पाया जाता है में चर का मान कॉपी कर रहे हैं। इसी प्रकार, संदर्भ द्वारा एक चर को बाध्य करके, आप इस तरह के एक आंतरिक चर को मूल चर के संदर्भ में बना रहे हैं, इस प्रकार मूल चर पर "परिवर्तन देखें" में सक्षम होना।

इसे इस तरह देखें। निम्नलिखित कोड ...

#include <iostream> 

int main() 
{ 
    int x = 0; 
    int y = 42; 
    auto qqq = [x, &y] { 
     std::cout << "x: " << x << std::endl; 
     std::cout << "y: " << y << std::endl; 
     ++y; 
    }; 
    x = y = 77; 
    qqq(); 
    qqq(); 
    std::cout << "final y: " << y << std::endl; 
} 

है (एक तरह से नहीं, बल्कि वास्तव में) वाक्यात्मक चीनी के लिए ...

#include <iostream> 

class MyLambda 
{ 
    private: 
     int x; 
     int& y; 

    public: 
     MyLambda(int x, int& y) : x(x), y(y) {} 

     void operator()() 
     { 
      std::cout << "x: " << x << std::endl; 
      std::cout << "y: " << y << std::endl; 
      ++y; 
     } 
}; 

int main() 
{ 
    int x = 0; 
    int y = 42; 
    MyLambda qqq = MyLambda(x, y); 
    x = y = 77; 
    qqq(); 
    qqq(); 
    std::cout << "final y: " << y << std::endl; 
} 
विशेष लैम्ब्डा वाक्य रचना के अपवाद और तथ्य यह है के साथ

कि आप कर सकते हैं ' टी लैम्ब्डा के प्रकार को सीधे संदर्भित नहीं करता है। बाद के कोड के साथ पूर्व की तुलना करके, आप बंद होने की अपनी समझ को दूर करने में सक्षम होना चाहिए।

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