2012-02-08 9 views
12

जीसीसी लैम्बडा कार्यों में संदर्भ द्वारा वैश्विक चर को गलत तरीके से कैप्चर करता प्रतीत होता है, भले ही उन्हें 'मूल्य से कैप्चर' के रूप में निर्दिष्ट किया गया हो। प्रिंट "एक = 9" यह कोड संकलित कर देगा और:जीसीसी गलत तरीके से लैम्ब्डा कार्यों में संदर्भ द्वारा वैश्विक चर को कैप्चर करता है?

#include <iostream> 

int a = 10; 

int main() 
{ 
    [=]() { a = 9; }(); 
    std::cout << "a = " << a << std::endl; 
    return 0; 
} 

हालांकि इस कोड संकलन नहीं होगा:

#include <iostream> 

int main() 
{ 
    int a = 10; 
    [=]() { a = 9; }(); // error: assignment of member 'main()::<lambda()>::a' in read-only object 
    std::cout << "a = " << a << std::endl; 
    return 0; 
} 

लेकिन स्पष्ट रूप से मूल्य से एक वैश्विक पर कब्जा करने और फिर इसे करने के लिए बताए त्रुटि देता है:

#include <iostream> 

int a = 10; 

int main() 
{ 
    [a]() { a = 9; }(); // assigment of read-only object 
    std::cout << "a = " << a << std::endl; 
    return 0; 
} 

मुझे पूरा यकीन है कि त्रुटि सही व्यवहार है - निहित कैप्चर इस त्रुटि को क्यों रोकता है? मैं सिर्फ नई सी ++ 11 विशेषताओं की खोज कर रहा हूं और गलती से कोड का पहला टुकड़ा लिखा है (यह महसूस नहीं कर रहा है कि यह एक त्रुटि होनी चाहिए) और तब आश्चर्यचकित हुआ जब मैंने जो मान लिया था, उसमें बदलाव स्थानीय स्तर पर प्रभावित हुआ।

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

+1

VS2010 सभी खातों पर एक ही तरह से व्यवहार करता है। दो कार्यान्वयन के लिए बिल्कुल असामान्य है, इसलिए मुझे लगता है कि यह एक बग नहीं हो सकता है। –

+6

आप यहां पर कैप्चर नहीं कर रहे हैं - स्वचालित संग्रहण के साथ केवल चर ही कब्जा कर लिया जा सकता है (और 'यह')। आप वैश्विक रूप से वैश्विक रूप से वैश्विक रूप से उपयोग कर रहे हैं, इस संदर्भ में लैम्बडा के बारे में कुछ खास नहीं है। – ildjarn

उत्तर

24

§5.1.2/11:

If a *lambda-expression(has an associated capture-default and its compound-statement odr-uses (3.2) this or a variable with automatic storage duration and the odr-used entity is not explicitly captured, then the odr-used entity is said to be implicitly captured; ...

वैश्विक चर (§3.7.1) स्थिर भंडारण अवधि है, इसलिए वैश्विक aपरोक्ष मूल्य द्वारा कब्जा कर लिया नहीं किया जाएगा। फिर भी, आप एक वैश्विक चर कहीं से भी एक्सेस कर सकते हैं ताकि

[=]() { a = 9; }(); 

की उम्मीद के रूप में 9 करने के लिए वैश्विक a सेट हो जाएगा।

स्पष्ट रूप से, पर कब्जा करने के लिए एक वैश्विक एक त्रुटि या यूबी होना चाहिए क्योंकि §5.1.2/10 का कहना है

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

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