2016-08-29 11 views
57

को समझने के लिए सी ++ में lambdas समझने की कोशिश कर कोशिश कर रहा है, क्या मुझे समझ नहीं आता यह है:lambdas

int multiplier = 5; 
auto timesFive = [multiplier](int a) { return a * multiplier; }; 
std::cout << timesFive(2) << '\n'; // Prints 10 

multiplier = 15; 
std::cout << timesFive(2) << '\n'; // Still prints 2*5 == 10 (???) - Should it be 30? 

कार्यक्रम timesFive() दूसरी बार आवश्यकता होने पर, मैं परिणाम 30. होने की उम्मीद लेकिन क्यों है परिणाम Still prints 2*5 == 10, prints 2*15 == 30 नहीं? शायद लैम्ब्डा फ़ंक्शन किसी भी तरह multiplier के मान को ट्रैक नहीं कर सकता है, भले ही हम इसे पहले से कैप्चर करने का प्रयास कर चुके हैं?

और वांछित परिणाम प्राप्त करने का तरीका क्या है?

+5

कृपया समस्या का वर्णन वर्णनात्मक बनाएं। हां, आप लैम्ब्स को समझने की कोशिश कर रहे हैं, लेकिन यह आपको वास्तव में जो पूछ रहा है उसके बारे में बहुत कुछ नहीं बताता है। (मैं इसे स्वयं संपादित करने पर विचार कर रहा था, लेकिन मुझे उन विचारों को पसंद नहीं आया जिनके साथ मैं आया था।) – jpmc26

उत्तर

91

आपने मूल्य से multiplier पर कब्जा कर लिया, जिसका अर्थ है कि इसे लैम्ब्डा में कॉपी किया गया था। आप संदर्भ द्वारा यह कब्जा करने के लिए की जरूरत है:

int multiplier = 5; 
auto timesFive = [&multiplier](int a) { return a * multiplier; }; 
std::cout << timesFive(2); 

multiplier = 15; 
std::cout << timesFive(2); 
+64

इसके अलावा, यदि आप वास्तव में इस व्यवहार को चाहते हैं, तो नाम 'timesFive' ​​थोड़ा भ्रामक –

+0

@SteveCox से अधिक है I यकीन है कि यह केवल एक अकादमिक उदाहरण है जो एक अवधारणा दिखा रहा है। हम इसे foo, foobar भी कह सकते हैं .... बेशक आप सही हैं, अगर वह असली दुनिया का उदाहरण था। – exilit

43

lambdas एक unnamable वर्ग और उसके उदाहरण के लिए syntatic चीनी हैं। कभी-कभी यह कोड आपके विस्तार का विस्तार करता है कि यह नामनीय वर्ग क्या हो रहा है यह समझने में सहायता कर सकता है।

struct anonymous_type { 
    capture_list; 
    auto operator()(arg_list) const -> return_value_clause_opt { 
    body 
    } 
    anonymous_type(capture_list_in):capture_list(capture_list_in) {} 
}; 

आप अपने सादे नाम से capture_list में एक चर सूची है, यह गुमनाम वर्ग के भीतर एक प्रति में नकल है:

[ capture_list ](arg_list) -> return_value_clause_opt { body }; 

बहुत मोटे तौर पर (छद्म कोड) हो जाता है।

तो अपने timesFive बन

struct __secret_name__ { 
    int multiplier; 
    int operator()(int a) const { return a*multiplier; } 
}; 
int multiplier = 5; 
auto timesFive = __secret_name__{multiplier}; 

यह बहुत स्पष्ट है कि उपरोक्त कोड में multiplier बदलते timesFive के व्यवहार में परिवर्तन नहीं होगा होना चाहिए।

आप नाम के सामने एक & रखते हैं, एक गैर constसंदर्भ गुमनाम वर्ग के भीतर रखा गया है।

struct __secret_name__ { 
    int& multiplier; 
    int operator()(int a) const { return a*multiplier; } 
}; 
int multiplier = 5; 
auto timesFive = __secret_name__{multiplier}; 

अब, multiplier बदलते timesFive के व्यवहार बदल जाएगा, क्योंकि timesFive एक संदर्भ रखती गुणक के लिए, इसकी एक प्रति नहीं।


कुछ विवरण संक्षिप्तता के लिए ऊपर छोड़ दिए गए हैं। नाम __secret_name__ केवल प्रदर्शनी के लिए है। लांबा के सदस्य चर वास्तव में सार्वजनिक नहीं हैं। लैम्ब्डा को तुच्छ रूप से रचनात्मक किया जा रहा है कार्यान्वयन परिभाषित किया गया है भले ही इसका डेटा है। आदि

+1

अच्छी अंतर्दृष्टि। बहुत पहले, सी ++ की "आंतरिक कार्यप्रणाली" प्राप्त करने के लिए, हमारे पास बजरने स्ट्राउस्ट्रप की सौजन्य थी। क्या इन दिनों कुछ भी समान है? आपने अपने छद्म कोड को कैसे अनुमान लगाया? सहज बोध? – blackpen

+2

@black मानक बताता है कि लैम्ब्डा क्या है।यह "as-if" के रूप में काफी नहीं है (:) 'loops, लेकिन यह बहुत स्पष्ट है। – Yakk

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