2013-04-09 7 views
11

मान लें कि मेरे पास एक लूप है जो लाखों बार दोहराता है। इस लूप के अंदर मेरे पास एक फंक्शन कॉल है।फ़ंक्शन पैरामीटर या स्थानीय चर

इस फ़ंक्शन के अंदर मुझे बहुत शुरुआत में बनाए गए कुछ अस्थायी चर पर काम करने की आवश्यकता है। अब, जो एक है बेहतर:

क) कोड की शुरुआत में अस्थायी चर बनाएँ, पाश की शुरुआत में यह प्रारंभ, और समारोह पैरामीटर के रूप में इसे पारित

ख) में सिर्फ स्थानीय अस्थायी चर बनाएं बुलाया समारोह की शुरुआत?

क्या यह उत्तरदायी प्रश्न है? मैं जानना चाहता हूं कि कौन सा बिंदु बेहतर अभ्यास माना जाता है, या कौन सा तेज़ है।

+1

क्लीनर कोड में जो भी परिणाम बेहतर अभ्यास है - इस मामले में, फ़ंक्शन के अंदर चर को घोषित करना। यदि आप चिंतित हैं कि कौन सा तेज़ है, तो बेंचमार्क। – cdhowie

+1

तो आप जो पूछ रहे हैं वह है: फ़ंक्शन में चर को बनाकर इसे पैरामीटर के रूप में पास करना? बहुत तुलनीय होना चाहिए। – cnicutar

+0

ठीक है, अच्छा, धन्यवाद। – user2252786

उत्तर

9

some_function() के लिए कुछ संभावित परिभाषाएं फेंक दें, जो फ़ंक्शन आप अपने लूप से कॉल करेंगे।

// Method 1 
void some_function() { 
    int temporary; 

    // Use temporary 
} 

// Method 2 
void some_function(int temporary) { 
    // Use temporary 
} 

// Method 3 
void some_function(int *temporary) { 
    // Use *temporary 
} 

विधि 1 सबसे इन विकल्पों में से बाहर पठनीय होने की संभावना है, और इसलिए यह एक मैं पसंद करेंगे जब तक आप एक वास्तव में कुछ और करने अच्छा कारण है है। यह तक की तुलना में तेज़ होने की संभावना है, जब तक कि आपका कंपाइलर फ़ंक्शन कॉल को रेखांकित कर रहा हो। यदि ऐसा है, तो सभी तीनों को बिल्कुल वही करने की संभावना है (यदि संकलक सूचक संकेतों को दूर करने में सक्षम नहीं है तो विधि 3 अभी भी धीमा हो सकता है)।

यदि कंपाइलर इनलाइन नहीं कर रहा है, तो विधि 2 विधि 1 की तुलना में धीमी होने की संभावना है। ऐसा इसलिए है क्योंकि, स्टैक-आवंटित स्मृति के मामले में, वे समान हैं - फ़ंक्शन तर्कों को संग्रहीत किया जा रहा है उसी तरह से ढेर स्थानीय लोग हैं। फ़ंक्शन तर्क और इस संदर्भ में स्थानीय के बीच एकमात्र अंतर यह है कि फ़ंक्शन तर्क को कॉलर द्वारा मान दिया जा सकता है। कॉलर से फ़ंक्शन में मान स्थानांतरित करने का यह चरण (सैद्धांतिक रूप से) आमंत्रण को धीमा करने जा रहा है।

विधि 3 लगभग निश्चित रूप से धीमा होने जा रहा है, क्योंकि अस्थायी स्मृति तक पहुंच में एक संकेत का स्तर शामिल होगा। किसी स्थानीय को एक्सेस करने की तुलना में एक पॉइंटर को डिफरेंस करना एक सस्ता ऑपरेशन नहीं है।

बेशक, यदि प्रदर्शन बिल्कुल महत्वपूर्ण है तो आपको इन दृष्टिकोणों को बेंचमार्क करना चाहिए। मुझे संदेह है कि विधि 1 सबसे तेज़ हो जाएगा (या कम से कम दूसरों की तुलना में धीमी नहीं) और इसके अतिरिक्त मेरे लिए अधिक पठनीय लगता है।

+0

उल्लेख करने वाली एकमात्र चीज स्टैक बनाम हीप var और संभव विखंडन है यदि var var "बड़ा" है। –

0

यदि पर इन दो दृष्टिकोणों के बीच एक सूक्ष्म अंतर है तो आप वैरिएबल को मूल्य के बजाय सूचक के रूप में पास कर रहे हैं। पॉइंटर कॉल स्टैक पर धकेल दिया जाएगा और मूल्य प्राप्त करने/सेट करने के लिए संदर्भित किया जाना होगा।

इसके विपरीत, इसे स्थानीय मान के रूप में सेट करना, या मूल्य से गुजरना, मूल्य को स्टैक पर रखेगा। यह महत्वपूर्ण नहीं है कि यह एक स्थानीय है या उस मामले में मूल्य से गुजरता है ... यद्यपि मूल्य के पारित होने के मामले में फ़ंक्शन के बाहर चर को कैसे नियंत्रित किया जाता है, इस पर आधारित एक संभावित चेतावनी है ... यदि यह संग्रहीत है एक चर (एक शाब्दिक मूल्य पारित नहीं) तो इसे स्मृति से प्राप्त किया जाना चाहिए और ढेर पर धक्का देना होगा। यदि यह फ़ंक्शन के अंदर एक शाब्दिक मूल्य से सेट है, तो यह स्टैक पर केवल एक शाब्दिक धक्का दिया गया है और एक मेमोरी चक्र बचाया गया है।

आपके द्वारा छोड़ा जाने वाला एक तीसरा विकल्प वैश्विक चर का उपयोग है।

ऑफ मौके पर मूल्य स्थिर रहता है, हमेशा, सबसे अच्छा जवाब # परिभाषित करता है और इसे सीधे शाब्दिक के रूप में कोड में संकलित करता है।

1

यदि फ़ंक्शन के बाहर चर की आवश्यकता नहीं है, तो यह फ़ंक्शन के अंदर होना चाहिए। यह संकलक को कोड को अनुकूलित करने का सर्वोत्तम काम करने के साथ-साथ कोड को सबसे अधिक पढ़ने योग्य और उपयोग करने में आसान बनाता है (यह आम तौर पर लागू होता है, "छोटे संभव स्कोप के साथ चर घोषित करें", हालांकि छोटे कार्यों के लिए, कुछ मुट्ठी घोषित करना समारोह के शीर्ष पर चर हर बार सबसे अच्छा विकल्प है)।

एक प्रदर्शन परिप्रेक्ष्य से, एक चर को एक चर से गुजरने के बराबर या स्थानीय चर होने से भी बदतर है। [और निश्चित रूप से, कंपाइलर सबकुछ इनलाइन कर सकता है और आप दोनों मामलों में बिल्कुल उसी कोड के साथ समाप्त हो सकते हैं, लेकिन यह आपके पास संकलक और कोड पर निर्भर है]।

जैसा कि अन्य लोगों ने उल्लेख किया है, स्थानीय परिवर्तक को पॉइंटर पास करने से मूल्य प्राप्त करने के लिए पॉइंटर तक पहुंचने के लिए "दंड" होगा। यह एक बड़ा अंतर नहीं बना सकता है, लेकिन यह लगभग निश्चित रूप से कुछ अंतर बनाता है। यह निश्चित रूप से अंतिम उपाय होना चाहिए। [ध्यान दें कि यदि चर बड़ा है, तो फ़ंक्शन में प्रतिलिपि पार करने का ओवरहेड अभी भी सूचक के ऊपरी हिस्से से भी बदतर हो सकता है। लेकिन अगर हम मानते हैं कि यह int या float जैसे साधारण प्रकार का है, तो एक सूचक के पास ध्यान देने योग्य ओवरहेड है]।

किसी भी समय प्रदर्शन पर कोई सवाल है, तो निश्चित रूप से आपको अपने कोड को बेंचमार्क करना चाहिए। इंटरनेट पर किसी और से पूछना सार्थक हो सकता है यदि सॉर्टिंग या ऐसा कुछ करने के लिए एल्गोरिदम के बीच कोई विकल्प है, लेकिन यदि यह कुछ और सूक्ष्म मतभेदों में "ऐसा करना बेहतर है या" यह मामला है, तो अंतर अक्सर होते हैं छोटा और आपके विशेष कंपाइलर का क्या "सैद्धांतिक रूप से बेहतर" से अधिक प्रभाव होगा।

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