मैं इस लंबर-संदर्भ ('और' ') को लंबोदर में क्यों नहीं पकड़ सकता?


91

मैं thisएक लंबोदर को पकड़ने (वस्तु गुणों को संशोधित करने) का सही तरीका समझता हूं :

auto f = [this] () { /* ... */ };

लेकिन मैं निम्नलिखित विशिष्टताओं के रूप में उत्सुक हूं जो मैंने देखा है:

class C {
    public:
        void foo() {
            // auto f = [] () { // this not captured
            auto f = [&] () { // why does this work?
            // auto f = [&this] () { // Expected ',' before 'this'
            // auto f = [this] () { // works as expected
                x = 5;
            };
            f();
        }

    private:
        int x;
};

जिस विषमता से मैं भ्रमित हूँ (और उत्तर देना चाहूँगा) इसीलिए निम्न कार्य करती है:

auto f = [&] () { /* ... */ }; // capture everything by reference

और मैं thisसंदर्भ द्वारा स्पष्ट रूप से कब्जा क्यों नहीं कर सकता :

auto f = [&this] () { /* ... */ }; // a compiler error as seen above.

6
तुम क्यों हैं चाहते हैं? उन चीजों के संदर्भ में जिनके लिए एक पॉइंटर का संदर्भ कभी भी उपयोगी हो सकता है: thisपरिवर्तित नहीं किया जा सकता है, यह एक संदर्भ को तेज बनाने के लिए पर्याप्त नहीं है ... और वैसे भी , यह वास्तव में मौजूद नहीं है , इसलिए यह है कोई वास्तविक जीवनकाल नहीं है, जिसका अर्थ है कि इसका कोई भी संदर्भ परिभाषा से झूलता रहेगा। thisप्रचलन है, लवलीन नहीं है।
अंडरस्कोर_ड

जवाबों:


111

कारण [&this]काम नहीं करता है क्योंकि यह एक वाक्यविन्यास त्रुटि है। प्रत्येक अल्पविराम-अलग पैरामीटर lambda-introducerएक है capture:

capture:
    identifier
    & identifier
    this

आप देख सकते हैं कि &thisवाक्य-रचना की अनुमति नहीं है। इसका कारण यह नहीं है कि आप thisसंदर्भ द्वारा कब्जा कभी नहीं करना चाहेंगे , क्योंकि यह एक छोटा कॉन्स्टेंट पॉइंटर है। आप केवल कभी इसे मूल्य से पारित करना चाहेंगे - तो भाषा सिर्फ thisसंदर्भ द्वारा कैप्चरिंग का समर्थन नहीं करती है ।

thisस्पष्ट रूप से पकड़ने के लिए आप के [this]रूप में उपयोग कर सकते हैं lambda-introducer

पहला जो captureहो सकता capture-defaultहै:

capture-default:
    &
    =

इसका मतलब है कि मैं जो भी उपयोग करता हूं, उसे संदर्भ ( &) या मूल्य के आधार पर =क्रमशः कैप्चर करता हूं - हालाँकि इसका उपचार thisविशेष है - दोनों ही मामलों में इसे पहले दिए गए कारणों के लिए मूल्य द्वारा कैप्चर किया जाता है (यहां तक ​​कि डिफ़ॉल्ट कैप्चर के साथ &, जिसका आमतौर पर मतलब है संदर्भ द्वारा कब्जा)।

5.1.2.7/8:

नाम देखने (3.4) के प्रयोजनों के लिए, this(9.3.2) के प्रकार और मूल्य का निर्धारण और आईडी-अभिव्यक्तियों को गैर-स्थैतिक वर्ग के सदस्यों का उपयोग करके कक्षा सदस्य अभिगम अभिव्यक्तियों (*this)(9.3.1), यौगिक-कथन [ लैम्ब्डा] को लैम्ब्डा-एक्सप्रेशन के संदर्भ में माना जाता है।

तो लैम्ब्डा कार्य करता है जैसे कि यह सदस्य नामों का उपयोग करते समय संलग्न सदस्य फ़ंक्शन का हिस्सा है (जैसे आपके उदाहरण में नाम का उपयोग x), इसलिए यह thisसदस्य फ़ंक्शन की तरह ही "निहित उपयोग" उत्पन्न करेगा ।

यदि एक लैम्ब्डा-कैप्चर में एक कैप्चर-डिफॉल्ट शामिल है &, जो लैम्ब्डा-कैप्चर में पहचानकर्ताओं द्वारा पहले नहीं किया जाएगा &। यदि एक लैम्ब्डा-कैप्चर में एक कैप्चर-डिफॉल्ट शामिल है =, जो लैम्ब्डा-कैप्चर में नहीं होता है thisऔर इसमें मौजूद प्रत्येक पहचानकर्ता द्वारा पूर्ववर्ती होगा &। एक पहचानकर्ता या thisलंबोदर-कैप्चर में एक से अधिक बार दिखाई नहीं देगा।

तो अगर आप उपयोग कर सकते हैं [this], [&], [=]या [&,this]एक के रूप में lambda-introducerकब्जा करने के लिए thisमूल्य द्वारा सूचक।

हालाँकि [&this]और [=, this]बीमार हैं। अंतिम मामले में, जीसीसी त्रुटियों के बजाय इसके लिए चेतावनी देता [=,this]है explicit by-copy capture of ‘this’ redundant with by-copy capture default


3
@KonradRudolph: क्या होगा यदि आप संदर्भ द्वारा कुछ चीज़ों को मूल्य और अन्य पर कब्जा करना चाहते हैं? या जो आप कब्जा करते हैं, उसके साथ बहुत स्पष्ट होना चाहते हैं?
Xeo

2
@KonradRudolph: यह एक सुरक्षा विशेषता है। आप गलती से उन नामों को पकड़ सकते हैं जिन्हें आप करने का इरादा नहीं रखते हैं।
एंड्रयू टॉमाज़ोस

8
@KonradRudolph: ब्लॉक स्तर के निर्माण जादुई रूप से उन वस्तुओं की ओर इशारा नहीं करते हैं, जिनका उपयोग वे एक नए अदृश्य अनाम प्रकार में करते हैं, जो तब संलग्नक दायरे से बच सकते हैं - बस एक अभिव्यक्ति में वस्तुओं के नाम का उपयोग करके। लैम्ब्डा कैप्चरिंग एक खतरनाक व्यवसाय का एक बहुत अधिक है।
एंड्रयू टॉमाज़ोस

5
@KonradRudolph मैं कहूंगा कि " [&]यदि आप एक नियंत्रण संरचना में पारित होने के लिए एक ब्लॉक बनाने की तरह कुछ कर रहे हैं" का उपयोग करें , लेकिन स्पष्ट रूप से कैप्चर करें यदि आप एक लैम्ब्डा का उत्पादन कर रहे हैं जो कम सरल उद्देश्यों के लिए उपयोग होने जा रहा है। [&]एक भयावह विचार है, यदि लंबोदा वर्तमान क्षेत्र को रेखांकित करने वाला है। हालांकि, लैम्ब्डा के कई उपयोग संरचनाओं को नियंत्रित करने के लिए ब्लॉकों को पारित करने के लिए सिर्फ तरीके हैं, और ब्लॉक उस दायरे से बाहर नहीं निकलेंगे जो इसे दायरे में बनाया गया था।
यक्क - एडम नेवरामोंट

2
@Ruslan: नहीं, thisएक कीवर्ड है, thisएक पहचानकर्ता नहीं है।
एंड्रयू तोमाज़ोस

6

क्योंकि &thisकैप्चर सूची में मानक नहीं है :

N4713 8.4.5.2 कैप्चर:

lambda-capture:
    capture-default
    capture-list
    capture-default, capture-list

capture-default:
    &
    =
capture-list:
    capture...opt
    capture-list, capture...opt
capture:
    simple-capture
    init-capture
simple-capture:
    identifier
    &identifier
    this
    * this
init-capture:
    identifier initializer
    &identifier initializer
  1. लैम्ब्डा कैप्चर के प्रयोजनों के लिए, एक अभिव्यक्ति संभावित रूप से स्थानीय संस्थाओं का संदर्भ देती है:

    7.3.३ यह अभिव्यक्ति संभावित रूप से संदर्भ देती है * यह।

इसलिए, मानक गारंटी देता है thisऔर *thisमान्य है, और &thisअमान्य है। इसके अलावा, कैप्चरिंग का thisमतलब है कैप्चरिंग *this(जो कि एक लवल्यू है, ऑब्जेक्ट ही) संदर्भ द्वारा , मान द्वारा सूचक को कैप्चर करने के बजाय !this


*thisमूल्य
sp2danny
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.