मुझे C ++ 11 क्लोजर के बारे में सही तरीके से सोचने std::function
और कैसे लागू किया जाता है और मेमोरी को कैसे संभाला जाता है , इसके बारे में कुछ जानकारी चाहिए ।
यद्यपि मैं समय से पहले अनुकूलन में विश्वास नहीं करता, मुझे नए कोड लिखते समय अपने विकल्पों के प्रदर्शन प्रभाव पर ध्यान से विचार करने की आदत है। मैं वास्तविक समय की प्रोग्रामिंग की एक उचित मात्रा में भी करता हूं, जैसे कि माइक्रोकंट्रोलर पर और ऑडियो सिस्टम के लिए, जहां गैर-नियतात्मक मेमोरी आवंटन / डील्लोकेशन पॉज़ से बचा जाना है।
इसलिए मैं C ++ लैम्ब्डा का उपयोग करने या न करने की बेहतर समझ विकसित करना चाहता हूं।
मेरी वर्तमान समझ यह है कि बिना किसी बंद किए हुए लैंबडा बिलकुल सी कॉलबैक जैसा है। हालांकि, जब पर्यावरण को मूल्य या संदर्भ द्वारा कैप्चर किया जाता है, तो स्टैक पर एक अनाम वस्तु बनाई जाती है। जब किसी फ़ंक्शन से वैल्यू-क्लोजर लौटाया जाना चाहिए, तो कोई इसे लपेटता है std::function
। इस मामले में क्लोजर मेमोरी का क्या होता है? क्या यह ढेर से ढेर की नकल है? क्या जब भी इसे मुक्त किया std::function
जाता है, तब इसे मुक्त कर दिया जाता है, क्या इसे संदर्भ-रूप में गिना जाता है std::shared_ptr
?
मुझे लगता है कि एक वास्तविक समय प्रणाली में मैं लंबोदा कार्यों की एक श्रृंखला स्थापित कर सकता हूं, बी को ए को एक निरंतरता तर्क के रूप में पारित कर सकता हूं, ताकि एक प्रसंस्करण पाइपलाइन A->B
बनाई जाए। इस मामले में, ए और बी क्लोजर एक बार आवंटित किया जाएगा। हालांकि मुझे यकीन नहीं है कि ये स्टैक या ढेर पर आवंटित किए जाएंगे। हालांकि सामान्य तौर पर यह वास्तविक समय प्रणाली में उपयोग करने के लिए सुरक्षित लगता है। दूसरी ओर यदि B कुछ लंबो फंक्शन C का निर्माण करता है, जिसे वह लौटाता है, तो C के लिए मेमोरी को बार-बार आवंटित और डील किया जाएगा, जो वास्तविक समय के उपयोग के लिए स्वीकार्य नहीं होगा।
छद्म कोड में, एक डीएसपी लूप, जो मुझे लगता है कि वास्तविक समय में सुरक्षित होने वाला है। मैं प्रसंस्करण ब्लॉक ए और फिर बी करना चाहता हूं, जहां ए अपनी दलील कहता है। ये दोनों कार्य std::function
वस्तुओं को वापस करते हैं, इसलिए f
एक std::function
वस्तु होगी , जहां इसका वातावरण ढेर पर संग्रहीत है:
auto f = A(B); // A returns a function which calls B
// Memory for the function returned by A is on the heap?
// Note that A and B may maintain a state
// via mutable value-closure!
for (t=0; t<1000; t++) {
y = f(t)
}
और जो मुझे लगता है कि वास्तविक समय कोड में उपयोग करने के लिए बुरा हो सकता है:
for (t=0; t<1000; t++) {
y = A(B)(t);
}
और जहाँ मुझे लगता है कि स्टैक मेमोरी का उपयोग बंद होने की संभावना है:
freq = 220;
A = 2;
for (t=0; t<1000; t++) {
y = [=](int t){ return sin(t*freq)*A; }
}
बाद के मामले में बंद का निर्माण लूप के प्रत्येक पुनरावृत्ति पर किया जाता है, लेकिन पिछले उदाहरण के विपरीत यह सस्ता है क्योंकि यह केवल फ़ंक्शन कॉल की तरह है, कोई ढेर आवंटन नहीं किया जाता है। इसके अलावा, मुझे आश्चर्य है कि अगर कोई कंपाइलर क्लोजर को "लिफ्ट" कर सकता है और इनलाइनिंग ऑप्टिमाइजेशन कर सकता है।
क्या ये सही है? धन्यवाद।
operator()
। ऐसा करने के लिए कोई "लिफ्टिंग" नहीं है, लैम्बदास कुछ खास नहीं हैं। वे एक स्थानीय फ़ंक्शन ऑब्जेक्ट के लिए केवल एक छोटा-हाथ हैं।