2012-09-17 10 views
7

मेरे पास लैम्ब्डा में लूप चर पैरामीटर के साथ लूप के अंदर एक लैम्ब्डा है। जब मैं इसे चलाता हूं, तो मुझे उम्मीद है कि संख्या 0-9 आउटपुट होगी। लेकिन चूंकि यह एक लैम्ब्डा है, इसलिए एक्स का तुरंत मूल्यांकन नहीं होता है।लैंपडा अंदर लूप

for(int x = 0; x < n; ++x) 
    { 
      vec.push_back(thread{[&x](){ 
        m.lock(); 
        cout << x << endl; 
        m.unlock(); 
      }}); 
    } 

आउटपुट:

0 
3 
3 
9 

आदि

अन्य भाषाओं के लिए समाधान के लिए एक अस्थायी चर बनाने के लिए हो सकता है,

for(int x = 0; x < n; ++x) 
    { 
      int tmp = x; 
      vec.push_back(thread{[&tmp](){ 
        m.lock(); 
        cout << tmp << endl; 
        m.unlock(); 
      }}); 
    } 

लेकिन यह है कि काम करने के लिए प्रतीत नहीं होता ।

एक जवाब के लिए मेरे खोज में, मैं इस सवाल Generalizing C++11 Threads class to work with lambda जो एक कंटेनर कि iterators अमान्य होगा का उपयोग नहीं की सिफारिश पर ठोकर खाई:

Threads receiving wrong parameters

बोनस देखें। क्यों होता है कि मूल्य के बजाय संदर्भ द्वारा/

उत्तर

11

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

शायद आप मूल्यों से कैप्चर करना चाहते थे। ऐसा करने के लिए, आप या तो कैप्चर विनिर्देश को [=] बनने या [x] बनने के लिए प्रतिस्थापित कर सकते हैं। उत्तरार्द्ध सुनिश्चित करता है कि केवल x तक पहुंचा जा सकता है जबकि पूर्व अन्य चरों को सुलभ करने की अनुमति देगा।

Btw, मैं स्पष्ट रूप से बल्कि lock() और unlock() का उपयोग कर ताला गार्ड से एक का उपयोग नहीं सलाह देते हैं। इसके साथ, आपके लूप का शरीर इस तरह कुछ दिखाई देगा:

vec.push_back(std::thread{[x](){ 
    std::lock_guard<std::mutex> kerberos(m); 
    std::cout << x << "\n"; 
}}); 
+0

मुझे मूर्खतापूर्ण लगता है। मैंने गलत समझा कि लैम्ब्डा अभिव्यक्तियों में क्या था और क्या था। इस oversimplified उदाहरण के लिए, हाँ एक लॉक_गार्ड उचित होगा। लेकिन असली एप्लिकेशन में, फ़ंक्शन बहुत कुछ करता है जिसे लॉक करने की आवश्यकता नहीं होती है। उस स्थिति में एक म्यूटेक्स उपयुक्त लॉकिंग और केवल महत्वपूर्ण भाग के आसपास अनलॉक होगा, सही? – SaulBack

+5

@ सॉलबैक: नहीं। आपको किसी भी तरह से 'lock_guard' का उपयोग करना चाहिए। यदि आप केवल कुछ कोड लॉक करना चाहते हैं, तो लॉक कोड को संलग्न करने के लिए '{}' के साथ एक स्पष्ट ब्लॉक का उपयोग करें। यह यहां मूल आरएआईआई कोडिंग है। –

+1

@ सॉलबैक: विशेष रूप से जटिल कोड में आप RAII का उपयोग करना चाहते हैं, उदाहरण के लिए, 'std :: lock_guard '! इस ** मामूली ** उदाहरण में मैं देख सकता हूं कि इसकी आवश्यकता नहीं है, लेकिन जिस क्षण यह थोड़ा और जटिल चीजें हाथ से बाहर हो जाती है। यदि आपको उस क्षेत्र को प्रतिबंधित करने की आवश्यकता है जहां लॉक आयोजित किया जाता है, तो स्कोप का उपयोग करें, यानी, ब्रेसिज़ की एक जोड़ी: '{<लॉक और कोड की आवश्यकता है यह यहां जाता है>}'। –

6

कब्जा पैरामीटर यह आप एक प्रतिलिपि बनाने के लिए चाहते हैं:

vec.push_back(std::thread{[x](){ 
    m.lock(); 
    std::cout << x << std::endl; 
    m.unlock(); 
}}); 

इस बार लैम्ब्डा वस्तु बनाया गया था पर x के मान की प्रतिलिपि जाएगा (उस समय धागा शुरू नहीं हुआ था)।

एक जवाब के लिए मेरे खोज में, मैं लैम्ब्डा जो एक कंटेनर कि iterators अमान्य होगा का उपयोग नहीं की सिफारिश के साथ काम करने के लिए इस सवाल पर ठोकर खाई सामान्यीकरण सी ++ 11 धागे वर्ग। यह क्यों होगा/

क्योंकि यह पूरी तरह से अलग कार्यान्वयन के बारे में बात कर रहा है जो सीधे pthreads लाइब्रेरी का उपयोग करता है। आप std::thread का उपयोग कर रहे हैं, जिसे सी ++ में काम करने के लिए डिज़ाइन किया गया है।

+0

क्या आप विस्तार कर सकते हैं कि एक कंटेनर में ptheads क्यों काम नहीं करेंगे जबकि std :: thread होगा? क्या यह कॉपी कन्स्ट्रक्टरों, चलती रचनाकारों, असाइनमेंट ऑपरेटर का मामला है? – SaulBack

3

मुद्दा यह है कि आप संदर्भ के अनुसार एक्स को कैप्चर कर रहे हैं। इस प्रकार जब प्रत्येक लूप के अंत में एक्स बढ़ाया जाता है, जो धागे में दिखाई देता है।

आप मूल्य से एक्स को कैप्चर करना चाहते हैं ताकि लैम्ब्डा केवल लम्बाडा बनने पर एक्स के मान का उपयोग कर सके।

for(int x = 0; x < n; ++x) 
{    
    vec.push_back(thread{[x](){ 
     m.lock(); 
     cout << tmp << endl; 
     m.unlock(); 
    }}); 
} 

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

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