2012-03-09 13 views
11

सी ++ मानक टेम्पलेट लाइब्रेरी में, एक 'कार्यात्मक' भाग है, जिसमें कई वर्गों ने () ऑपरेटर को अधिभारित किया है।एसटीएल कार्यात्मक - क्यों?

क्या यह सी ++ में ऑब्जेक्ट्स के रूप में कार्यों का उपयोग करने के लिए कोई सुविधा लाता है?

हम इसके बजाय फ़ंक्शन पॉइंटर का उपयोग क्यों नहीं कर सकते? कोई उदाहरण?

+1

[सी ++ फ़ैक्टर - और उनके उपयोग] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/356950/c-functors-and-their-uses)। –

उत्तर

10

बेशक, हमेशा समारोह वस्तुओं के बजाय समारोह संकेत का उपयोग कर सकते हैं, लेकिन वहाँ कुछ लाभ जो वस्तुओं में कार्य से अधिक प्रदान समारोह संकेत, अर्थात् हैं:

  • बेहतर प्रदर्शन:

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

  • समारोह वस्तुओं स्मार्ट कार्य हैं:

समारोह वस्तुओं अन्य सदस्य कार्यों हो सकता है और attributes.This मतलब यह है कि समारोह वस्तुओं एक राज्य है। वास्तव में, फ़ंक्शन ऑब्जेक्ट द्वारा प्रतिनिधित्व किया गया एक ही फ़ंक्शन, एक ही समय में अलग-अलग राज्य हो सकता है। सामान्य कार्यों के लिए यह संभव नहीं है। फ़ंक्शन ऑब्जेक्ट्स का एक अन्य लाभ यह है कि आप उन्हें चलाने/कॉल करने से पहले रनटाइम पर प्रारंभ कर सकते हैं।

  • जेनेरिक प्रोग्रामिंग की शक्ति:

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

4

हम इसके बजाय फ़ंक्शन पॉइंटर का उपयोग क्यों नहीं कर सकते? कोई उदाहरण?

का उपयोग सी शैली समारोह सूचक इनलाइन करने के लाभ का लाभ उठाने नहीं कर सकते। फ़ंक्शन पॉइंटर को आमतौर पर लुकअप के लिए अतिरिक्त संकेत की आवश्यकता होती है।
हालांकि, operator() अधिभारित है तो संकलक के लिए inline कोड के लिए बहुत आसान है और अतिरिक्त कॉल सहेजें, इसलिए प्रदर्शन में वृद्धि।

अतिभारित operator() के अन्य लाभ यह है कि, एक एक समारोह जो परोक्ष समझता है तर्क के रूप में समारोह वस्तु डिजाइन कर सकते हैं; इसे एक अलग समारोह के रूप में पास करने की आवश्यकता नहीं है। हाथ कोडित कार्यक्रम कम, कम बग और बेहतर पठनीयता।

This question बजेर्न स्ट्राउस्ट्रप (सी ++ आविष्कारक) वेबपृष्ठ से उस पहलू को अच्छी तरह से समझाता है।

सी ++ मानक (खाका) लाइब्रेरी, अतिभारित operator() साथ कार्यात्मक प्रोग्रामिंग का उपयोग करता है अगर यह आवश्यक है।

+0

कुछ कंपाइलर्स वास्तव में एक अप्रत्यक्ष कॉल और इनलाइन को फ़ंक्शन पॉइंटर के माध्यम से हटा देंगे, जब फ़ंक्शन पॉइंटर का मान निरंतर होता है और संकलन-समय पर ज्ञात होता है। –

2

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

इसके अलावा इसमें संभावित फायदे हैं कि ज्यादातर मज़दूर साधारण कक्षाएं हैं जिनके लिए कंपाइलर की पूर्ण परिभाषा है और फ़ंक्शन कॉल में इनलाइनिंग प्रदर्शन में सुधार कर सकते हैं। यही कारण है कि std::sort सी पुस्तकालय से qsort से बहुत तेज हो सकता है।

3

> क्या यह सी ++ में ऑब्जेक्ट्स के रूप में कार्यों का उपयोग करने के लिए कोई सुविधा लाता है?

हां: सी ++ टेम्पलेट तंत्र अन्य सभी सी/सी ++ प्रोग्रामिंग शैलियों (सी शैली और ओओपी शैली, नीचे देखें) की अनुमति देता है।

> हम इसके बजाय फ़ंक्शन पॉइंटर का उपयोग क्यों नहीं कर सकते? कोई उदाहरण?

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


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

सी ++ में, वांछित गुणों के साथ कुछ भी एक वस्तु के रूप में देखा जा सकता है। इस मामले में, एक साधारण सी फ़ंक्शन पॉइंटर भी एक ऑब्जेक्ट है। यह इस बात का तात्पर्य नहीं है कि वांछित नहीं होने पर ओओपी प्रतिमानों का उपयोग किया जाता है; यह टेम्पलेट तंत्र का उपयोग करने का एक उचित तरीका है।


प्रदर्शन अंतर को समझने के लिए, प्रोग्रामिंग (-language) शैलियों/मानदंड और उनके संभव अनुकूलन की तुलना:

सी शैली: के बंद होने के साथ

  • समारोह सूचक (" यह "ओओपी में, कुछ संरचना के लिए सूचक) पहले पैरामीटर के रूप में।
  • फ़ंक्शन को कॉल करने के लिए, फ़ंक्शन का पता पहले एक्सेस किया जाना चाहिए।
  • यह 1 संकेत है; कोई इनलाइनिंग संभव नहीं है।

सी ++ (और जावा) OOP शैली: एक वस्तु आभासी कार्यों के साथ एक वर्ग से प्राप्त होने वाले

  • संदर्भ।
  • संदर्भ 1 सूचक है।
  • आभासी तालिका में सूचक 2 सूचक है।
  • वर्चुअल-टेबल में फ़ंक्शन पॉइंटर तीसरा पॉइंटर है।
  • यह 3 संकेत हैं; कोई इनलाइनिंग संभव नहीं है।

सी ++ टेम्पलेट शैली:

  • साथ() फ़ंक्शन किसी ऑब्जेक्ट की प्रतिलिपि।
  • उस ऑब्जेक्ट के प्रकार के बाद से कोई वर्चुअल-टेबल संकलित समय पर ज्ञात नहीं है।
  • फ़ंक्शन का पता संकलन समय पर जाना जाता है।
  • 0 संकेतक हैं; संभव inlining।

सी ++ टेम्पलेट्स पर्याप्त बहुमुखी ऊपर अन्य दो शैलियों अनुमति देने के लिए हैं, और वे भी मात कर सकते हैं इनलाइन करने के मामले ... में

संकलित कार्यात्मक भाषाओं: (छोड़कर JVM और जावास्क्रिप्ट लक्ष्य प्लेटफॉर्म के रूप में "उचित पूंछ कॉल" गायब होने के कारण)

  • फ़ंक्शन पॉइंटर और मशीन रजिस्टरों में इसके बंद होने का संदर्भ।
  • आमतौर पर यह कोई फ़ंक्शन "कॉल" नहीं होता है लेकिन कूद की तरह एक गोटो है।
  • कार्यों को स्टैक की आवश्यकता नहीं है, वापस कूदने के लिए कोई पता नहीं, कोई पैरामीटर नहीं है और न ही स्टैक पर स्थानीय चर हैं।
  • फ़ंक्शंस में उनके कचरे को संग्रहित बंद करने के लिए पैरामीटर होते हैं और अगले फ़ंक्शन को पॉइंटर कहा जाता है।
  • सीपीयू के लिए कूदने की भविष्यवाणी करने के लिए, फ़ंक्शन का पता जितनी जल्दी हो सके रजिस्टर में लोड किया जाना चाहिए।
  • यह संभव कूद पूर्वानुमान के साथ 1 संकेत है; सबकुछ जितना तेज़ है उतना तेज़ है।
+0

मुझे यकीन नहीं है कि यह ओपी द्वारा पूछे गए किसी भी प्रश्न का उत्तर कैसे देता है। –

+0

@ एएलएस: मैंने सीधे प्रश्न से मेल खाने के लिए अपना जवाब संपादित कर लिया है। मेरे अधिकांश उत्तर में मुझे लगता है कि अप्रत्यक्ष पूछे जाने वाली जानकारी क्या है। – comonad