2010-12-13 10 views
16

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

संपादित करें: उदाहरण के लिए, मैंने धागे में कॉल को स्थानांतरित करने के लिए एक स्निपेट लिखा है। यहां एक नमूना है जो ऐसा करता है।

extern "C" __declspec(dllexport) void parser_file_updated(Parser* p, const char* filename, int offset, int added) { 
    std::string file(filename); 
    p->make_call([=]() { 
     p->file_updated(std::move(file), offset, added); 
    }); 
} 

लेकिन स्पष्ट रूप से, फ़ाइल चर अतीत लैम्ब्डा definition- जीने के लिए और वास्तव में, लैम्ब्डा केवल एक बार कहा जाता है की जरूरत नहीं है, इसलिए मैं नकल ले जाया गया।

+3

मेरा अनुमान यह होगा कि कंपेलरों के लिए सामान्य रूप से यह पता लगाना बहुत मुश्किल है। क्या आप उदाहरण कोड प्रदान कर सकते हैं? – fredoverflow

+0

पाठ्यक्रम के "जैसे" नियम है। लेकिन मुझे लगता है कि आप ऐसे मामले के बारे में सोच रहे हैं जहां प्रतिलिपि ctor और/या ctor को साइड इफेक्ट्स हैं, इसलिए आप अंतर बता सकते हैं। दिलचस्प सवाल – aschepler

+0

@aschepler: अगर मुझे सही ढंग से याद किया जाता है, तो संकलक को प्रतिलिपि के दुष्प्रभावों को अनदेखा करने और रचनाकारों को स्थानांतरित करने की अनुमति है। @DeadMG: मुझे लगता है जैसे इसे अनुकूलित किया जा सकता है, क्या आपने इसे आजमाया है? –

उत्तर

12

यदि आप कभी भी उस चर को संदर्भित नहीं करते हैं, तो क्या संकलक इसे परिणामस्वरूप कार्य ऑब्जेक्ट में स्थानांतरित करने की अनुमति देता है?

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

दुर्भाग्य से, सी ++ 11 में "कैप्चर कैप्चर" के लिए वाक्यविन्यास नहीं है। आईएमएचओ, यह शर्म की बात है। लेकिन std :: बाइंड इसका समर्थन करता है। यह इस तरह से एक लैम्ब्डा अभिव्यक्ति के साथ std :: बाँध गठबंधन करने के लिए संभव हो जाना चाहिए:

void foo(char const* p) { 
    string s = p; 
    auto fun = bind([](string const& s){ 
     ... 
    },move(s)); 
    fun(); 
} 

ताकि स्ट्रिंग समारोह वस्तु में ले जाया जाता है।

आप केवल एक बार इस समारोह कॉल करने के लिए इरादे हैं और फिर समारोह वस्तु से बाहर स्ट्रिंग ले जाना चाहते हैं, तो आप एक गैर स्थिरांक संदर्भ का उपयोग कर सकते हैं:

void foo(char const* p) { 
    string s = p; 
    auto fun = bind([](string & s) { 
     some_other_func(move(s)); 
    },move(s)); 
    fun(); 
} 

ध्यान दें कि, तुम नहीं करता है, तो यहाँ बाँध का उपयोग लेकिन लैम्ब्डा वस्तु के निर्माता, रों की एक प्रतिलिपि बनाने स्ट्रिंग समारोह वस्तु से बाहर जाने देना चाहते हैं परिवर्तनशील कीवर्ड की आवश्यकता है:

void foo(char const* p) { 
    string s = p; 
    auto fun = [=]() mutable { 
     //   ^^^^^^^ 
     some_other_func(move(s)); 
    }; 
    fun(); 
} 

क्योंकि अन्यथा बंद प्रकार के ऑपरेटर() फ़ंक्शन const- हो जाएगा योग्यता जो बदले मेंबनाता हैएक कॉन्स-योग्य स्ट्रिंग।

सी ++ 14 में लैम्ब्डा कैप्चर क्लॉज थोड़ा और लचीला हो गया। अब हम लिख सकते हैं

void foo(char const* p) { 
    string s = p; 
    auto fun = [s=move(s)]() mutable { // #1 
     some_other_func(move(s));  // #2 
    }; 
    fun(); 
} 

जहां लैम्ब्डा वस्तु और # 2 चाल स्ट्रिंग मान बाहर (कैसे some_other_func वास्तव में घोषित किया जाता है पर निर्भर करता है) में # 1 चाल स्ट्रिंग मान।

+0

ए सी ++ कंपाइलर ऐसा कोई अनुकूलन कर सकता है जो ऐसा लगता है, बशर्ते अवलोकन योग्य व्यवहार समान हो। इस विशिष्ट मामले में यह बिना किसी सूचना के ऑब्जेक्ट को स्थानांतरित कर सकता है, इसलिए इसकी अनुमति है। यह आपके जवाब को वास्तव में गलत बनाता है। – nwp

+0

@nwp: सभी उद्देश्यों और उद्देश्यों के लिए, मैं असहमत हूं। अवलोकन करने योग्य व्यवहार में इस तथ्य को शामिल किया गया है कि एक प्रतिलिपि ctor या एक चाल ctor आह्वान किया जाता है - यह मानते हुए कि कार्य अलग-अलग व्यवहार करते हैं - जो निश्चित रूप से, एक चाल ctor का उद्देश्य है। जैसा कि नियम आपको लागत कम करने में मदद नहीं करता है। – sellibitze

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