2013-04-17 10 views
8
#include <iostream> 

void foo(int k) { 
    static auto bar = [&]{ 
     std::cout << k << std::endl; 
    }; 
    bar(); 
} 

int main() { 
    foo(1); foo(2); foo(3); // output is correct: 1, 2, 3 
} 

चेक समारोह foo, एक कैसे स्थिर लैम्ब्डा संदर्भ द्वारा कश्मीर कैप्चर कर रहा है। ऐसा लगता है, और यह int के बजाय अधिक जटिल डेटाटाइप के साथ हो रहा है।संदर्भ स्थिर चर परिभाषा में कब्जा

क्या यह उम्मीद है? क्या कोई गारंटी है कि के का पता foo के प्रत्येक आमंत्रण के लिए समान होगा, या यह UB है?

अग्रिम धन्यवाद, और खेद अगर यह पहले से उत्तर दिया गया (मैं सफलता के बिना एक समान प्रश्न खोजने की कोशिश की थी)

+0

एडम आप एक मील से बिंदु चूक गए, मुझे डर है – sehe

उत्तर

4

यह अपरिभाषित व्यवहार है।

प्रति पैरा

5.2.2 सी ++ 11 समारोह कॉल भाव के बारे में स्टैंडर्ड और उनके मापदंडों के प्रारंभ के/4:

[...] एक पैरामीटर के जीवनकाल समाप्त होता है जब समारोह जिसमें परिभाषित रिटर्न है। प्रत्येक पैरामीटर का प्रारंभ और विनाश कॉलिंग फ़ंक्शन के संदर्भ में होता है। [...]

इसलिए, आपका लैम्ब्डा एक संदर्भ संग्रहीत करेगा जो फंक्शन कॉल रिटर्न के तुरंत बाद लटकता हो जाता है।

इस मामले में, कार्यान्वयन मुक्त (और संभावना) प्रत्येक कार्य कॉल, जो शायद कारण है कि आप की उम्मीद उत्पादन देख रहे हैं है के लिए एक ही पते पर समारोह पैरामीटर बनाना है।

हालांकि, इस व्यवहार स्टैंडर्ड द्वारा अनिवार्य नहीं है - इसलिए, आप उस पर निर्भर नहीं होना चाहिए (यदि यह मामला था, अपने कोड कानूनी होगा की वजह से 3.8/7)।

+0

महान उत्तर! 3.8/7 क्या कहता है? –

+1

@ Josemanuel: "*, तो एक वस्तु का जीवन समाप्त हो गया है और भंडारण, एक सूचक जो वस्तु पर कब्जा कर लिया पुन: उपयोग किया जाता है या जारी किया, एक नई वस्तु भंडारण स्थान पर कब्जा कर लिया जो मूल वस्तु पर बनाया गया है से पहले कि उठाई के बाद मूल वस्तु, एक संदर्भ है कि मूल वस्तु के रूप में भेजा, या मूल वस्तु स्वचालित रूप से नई वस्तु को देखें और का नाम करने के लिए, एक बार नई वस्तु के जीवनकाल शुरू कर दिया है, नई वस्तु हेरफेर करने के लिए इस्तेमाल किया जा सकता , अगर * [...] "- और निम्नानुसार स्थितियां हैं जो आपके उदाहरण से संतुष्ट हैं। –

+0

* "प्रत्येक फंक्शन कॉल के लिए एक ही पते पर फ़ंक्शन पैरामीटर बनाने के लिए कार्यान्वयन मुक्त (और संभवतः)" * - नि: शुल्क है, लेकिन वास्तव में नहीं * "संभवतः" *, यह मानते हुए कि वे आमतौर पर स्टैक पर पारित किए जाएंगे (जिनके लिए शीर्ष पता बहुत ही असंभव * हर बार समारोह कहलाता है)। या क्या आपने इसका मतलब सिर्फ अपने उदाहरण में किया था, जहां यह वास्तव में * "संभावना" * है कि स्टैक पॉइंटर व्यक्तिगत फ़ंक्शन कॉल के बीच नहीं बदलेगा? –

1

कारण यह शायद "काम" है अपने उदाहरण में है कि कॉल स्टैक हमेशा एक ही तरीके अस्तर किया जाता है। इसके बजाय इसे आज़माएं और देखें कि क्या आपको अभी भी "अपेक्षित" आउटपुट मिलता है या नहीं।

#include <iostream> 

void foo(int k) { 
    static auto bar = [&]{ 
     std::cout << k << std::endl; 
    }; 
    bar(); 
} 

void baz(int k) { 
    std::cout << "baz: "; 
    foo(k); 
} 

int main() { 
    foo(1); baz(2); foo(3); 
} 
+0

मैं clang3.2 और g ++ 4.7.2 का उपयोग कर रहा हूं, और आपका संस्करण "काम" भी लगता है। लेकिन मैंने बस * foo (k + 1) * के साथ अपने * foo (k) * को बदलने की कोशिश की और अनुमान लगाया, अब मेरे पास दो कंपाइलर्स से अलग आउटपुट हैं :) (clang: 1, 2, 3 और gcc: 1 , 3, 3) –

+1

बिंदु यह नहीं है कि आप किस कंपाइलर का उपयोग कर रहे हैं; मुद्दा यह है कि व्यवहार अपरिभाषित है। इसका मतलब है कि यह किसी मामले में और दूसरे में दुर्घटना में काम कर सकता है। इससे भी बदतर, यह आपकी हार्ड ड्राइव को प्रारूपित कर सकता है, आपके ऑक्सीजन की आपूर्ति को रोक सकता है या अन्य नुकसान का कारण बन सकता है। –

+1

मुझे लगता है कि आपको इसे काम करने के लिए [कुछ और पैरामीटर] (http://ideone.com/3B37yt) जोड़ने की आवश्यकता है। –

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