दिलचस्प पोस्ट
AngularJS: एनजी-मॉडल चेकबॉक्स के लिए एनजी-चेक करने के लिए बाध्य नहीं है एचटीएमएल / पीएचपी – फॉर्म – इनपुट सरणी के रूप में पीएचपी स्ट्रिंग मैच पूरे शब्द की जगह है रूबी में डिबगिंग 1.9 एक सेवा के भीतर प्रसारण प्राप्तकर्ता आप कैसे कर सकते हैं oncut, oncopy, और onpaste jQuery में संभाल? मैं टैब और रिक्त स्थान को क्यों नहीं मिला? एंड्रॉइड लंबित इरादा अधिसूचना समस्या IOS में फ़ाइल डाउनलोड और खोलना UIViewController पर UIViewController पेश करने का प्रयास करना, जिसका दृश्य विंडो पदानुक्रम में नहीं है एक फ़ोल्डर के अंदर सबफ़ोल्डर फ़ाइलों का लगातार उपयोग करें सी में अपारदर्शी सूचक क्या है? जावा में जेसन को सूची कैसे परिवर्तित करें मेरा ग्राहक सॉकेट क्या प्राप्त करता है, जो मेरे सर्वर सॉकेट भेजता है? ld: फ़ाइल नहीं मिली: लिंकर कमांड विफलता कोड 1 के साथ विफल हुआ

क्या सी + + में मूल्य से गुजारें या निरंतर संदर्भ से उत्तीर्ण हो?

क्या सी + + में मूल्य से गुजारें या निरंतर संदर्भ से उत्तीर्ण हो?

मैं सोच रहा हूं कि बेहतर अभ्यास क्या है मुझे एहसास है कि निरंतर संदर्भ से पारित होने के कार्यक्रम में बेहतर प्रदर्शन प्रदान करना चाहिए क्योंकि आप चर की एक प्रति नहीं बना रहे हैं।

वेब के समाधान से एकत्रित समाधान "क्या सी + + में मूल्य से गुजारें या निरंतर संदर्भ से उत्तीर्ण हो?"

इसे आम तौर पर सबसे अच्छा अभ्यास 1 की सिफारिश करने के लिए सभी प्रकार के const रेफरी से पास का उपयोग करने के लिए सिफारिश की गई थी, इसके अलावा इटेटर के लिए और फंक्शन ऑब्जेक्ट्स (लैम्ब्दास, std::*_function )

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

सी +11 के साथ, हमने चाल शब्दों को हासिल किया है। संक्षेप में, शब्दों को स्थानांतरित करने की अनुमति है कि, कुछ मामलों में, एक ऑब्जेक्ट इसे "कॉपी करके" बिना "मूल्य" के पास किया जा सकता है विशेष रूप से, यह वह मामला है, जिस वस्तु को आप गुजर रहे हैं वह एक रैवल्यू है

अपने आप में, एक ऑब्जेक्ट को ले जाने के संदर्भ में कम से कम उतना महंगी होती है हालांकि, कई मामलों में एक समारोह आंतरिक रूप से किसी वस्तु की प्रतिलिपि बना देगा – यानी यह तर्क के स्वामित्व को ले जाएगा। 2

इन स्थितियों में हमारे पास निम्न (सरलीकृत) ट्रेड-ऑफ है:

  1. हम संदर्भ से ऑब्जेक्ट पास कर सकते हैं, फिर आंतरिक रूप से कॉपी कर सकते हैं।
  2. हम मूल्य से ऑब्जेक्ट पास कर सकते हैं।

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

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


एक ऐतिहासिक नोट:

दरअसल, किसी भी आधुनिक संकलक को यह समझने में सक्षम होना चाहिए कि मान से गुजरना महंगा है, और यदि संभव हो तो कॉन्स्ट रीफ का उपयोग करने के लिए कॉल पर पूरी तरह से कनवर्ट करें।

सिद्धांत रूप में। अभ्यास में, कंपलर फ़ंक्शन के बाइनरी इंटरफ़ेस को तोड़ने के बिना हमेशा इसे बदल नहीं सकते हैं। कुछ विशेष मामलों में (जब फ़ंक्शन इनलाइन होता है) तो प्रति वास्तव में लुप्त हो जाएगा यदि संकलक यह पता लगा सकता है कि फ़ंक्शन में क्रियाओं के माध्यम से मूल ऑब्जेक्ट नहीं बदलेगा।

लेकिन सामान्य तौर पर कंपाइलर यह निर्धारित नहीं कर सकता है, और सी ++ में ले जाने के शब्दों का आगमन इस अनुकूलन को बहुत कम प्रासंगिक बना दिया है।


स्कॉट मेयेर में 1 उदाहरण, प्रभावी सी ++

2 यह विशेष रूप से ऑब्जेक्ट कन्स्ट्रक्टरों के लिए सच है, जो तर्कों को ले सकता है और उन्हें आंतरिक रूप से निर्मित ऑब्जेक्ट के राज्य का हिस्सा बन सकता है।

संपादित करें: डेव इब्राहीम का नया लेख सीपीपी-अगले पर:

गति चाहते हैं? मूल्य से गुजारें


स्ट्रक्चर्स के लिए मान से पास करें जहां नकल सस्ते है, अतिरिक्त लाभ यह है कि संकलक यह मान सकता है कि ऑब्जेक्ट उपनाम नहीं हैं (वही ऑब्जेक्ट नहीं हैं) पास-बाय-रेफ़ेस का उपयोग करके संकलक हमेशा ऐसा नहीं मान सकता है। सरल उदाहरण:

 foo * f; void bar(foo g) { gi = 10; f->i = 2; gi += 5; } 

कंपाइलर इसे में अनुकूलित कर सकते हैं

 gi = 15; f->i = 2; 

क्योंकि यह जानता है कि एफ और जी समान स्थान साझा नहीं करते हैं। यदि g एक संदर्भ (foo &) था, तो संकलक को यह नहीं माना जा सकता था। चूंकि जी को फिर एफ-> i के द्वारा स्थानांतरित किया जा सकता है और उसे 7 का मान होना चाहिए। इसलिए संकलक को स्मृति से जी के नए मूल्य को पुनः प्राप्त करना होगा।

अधिक मूल्यवान नियमों के लिए, यहां हंड कंस्ट्रक्टर्स लेख (अत्यधिक अनुशंसित पढ़ने) में पाए गए नियमों का एक अच्छा सेट है।

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

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

उदाहरण: एक स्ट्रिंग अपरकेस बनाने और अपरकेस संस्करण को वापस करने के लिए, हमेशा मूल्य से गुजरना चाहिए: किसी को भी इसकी प्रतिलिपि किसी भी तरह से लेनी होगी (कोई भी संदर्भ संदर्भ सीधे नहीं बदल सकता है) – इतना बेहतर है कि इसे जितना संभव हो उतना पारदर्शी बना सके कॉलर और उस प्रति शीघ्र बनाओ ताकि कॉलर जितना संभव हो सके उतना अनुकूलित कर सके – जैसा कि उस पेपर में बताया गया है:

 my::string uppercase(my::string s) { /* change s and return it */ } 

हालांकि, यदि आपको पैरामीटर को वैसे भी बदलने की आवश्यकता नहीं है, तो इसे const के संदर्भ में लें:

 bool all_uppercase(my::string const& s) { /* check to see whether any character is uppercase */ } 

हालांकि, यदि आप पैरामीटर का उद्देश्य तर्क में कुछ लिखना है, तो इसे गैर-कॉन्स्ट संदर्भ से पास करें

 bool try_parse(T text, my::string &out) { /* try to parse, write result into out */ } 

प्रकार पर निर्भर करता है आप एक संदर्भ और dereference बनाने के लिए होने के छोटे उपरि जोड़ रहे हैं। उन प्रकार के प्रकार के लिए जिनकी तुलना में मूल प्रति सीटीओर का उपयोग किया जाता है, उनको पॉइंटर्स से बराबर या छोटा होता है, यह संभवतः मूल्य से गुजरता है।

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

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

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

लगता है जैसे आपको अपना जवाब मिला। मूल्य से गुजरना महंगा है, लेकिन आपको इसकी आवश्यकता के साथ काम करने की एक कॉपी प्रदान करता है।

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

गैर-टेम्पलेट फंक्शन के इंटरफेस को डिज़ाइन करते समय यह सामान्य रूप से काम करता है:

  1. मूल्य से गुजारें अगर फ़ंक्शन पैरामीटर को संशोधित नहीं करना चाहता है और मूल्य कॉपी करने के लिए सस्ता है (इंट, डबल, फ्लोट, चार, बूल, आदि) ध्यान दें कि std :: string, std :: vector, और बाकी मानक लाइब्रेरी में कंटेनरों का नहीं है)

  2. कॉन्स्ट पॉइंटर से पास करें यदि मूल्य की प्रतिलिपि करने के लिए महंगा है और फ़ंक्शन मूल्य को संशोधित नहीं करना चाहता है और नल फ़ंक्शन हैंडल के मान है।

  3. गैर-कॉन्सेंट पॉइंटर से पास करें यदि मूल्य की प्रतिलिपि करने के लिए महंगा है और फ़ंक्शन मूल्य को संशोधित करना चाहता है और NULL एक ऐसा मान है जो फ़ंक्शन हैंडल है।

  4. कॉन्स्ट संदर्भ द्वारा पास करें जब मूल्य की प्रतिलिपि करने के लिए महंगा है और फ़ंक्शन निर्दिष्ट मान को संशोधित नहीं करना चाहता है और नल एक वैध मान नहीं होगा यदि कोई सूचक इसके बजाय उपयोग किया गया था

  5. गैर-कॉन्स्ट संदर्भ से पास करें जब मूल्य की प्रतिलिपि करने के लिए महंगा है और फ़ंक्शन को संदर्भित मान को संशोधित करना है और नल एक मान्य मान नहीं होगा यदि कोई सूचक इसके बजाय उपयोग किया गया था।

अंगूठे के नियम के रूप में, वर्गों के लिए गैर-वर्ग प्रकारों और const संदर्भ के लिए मान यदि कोई क्लास वास्तव में छोटा है तो मूल्य से गुजरना संभव है, लेकिन अंतर कम है जो वास्तव में आप से बचना चाहते हैं, वह कुछ विशाल वर्ग को मूल्य से गुजर रहा है और यह सब डुप्लिकेट कर रहा है – यदि आप गुजर रहे हैं तो यह एक बहुत बड़ा फर्क पड़ेगा, कहें, इसमें एक स्टडी :: वेक्टर जिसमें कुछ तत्व हैं।

छोटे प्रकार के मूल्य के लिए पास करें

बड़े प्रकार के लिए कॉन्स्ट संदर्भ (बड़े की परिभाषा मशीनों के बीच भिन्न हो सकती है) से गुजरती हैं, लेकिन सी ++ 11 में, मूल्य से गुजरती हैं यदि आप डेटा का उपभोग करने जा रहे हैं, क्योंकि आप चाल शब्दों का फायदा उठा सकते हैं। उदाहरण के लिए:

 class Person { public: Person(std::string name) : name_(std::move(name)) {} private: std::string name_; }; 

अब कॉलिंग कोड होगा:

 Person p(std::string("Albert")); 

और केवल एक ऑब्जेक्ट बनाया जाएगा और क्लास Person में सीधे सदस्य नाम में ले जाया जाएगा। यदि आप कॉन्स्ट संदर्भ द्वारा पास करते हैं, तो उसे एक नाम के नाम के लिए प्रतिलिपि बना दिया जाएगा।

सरल अंतर: – फ़ंक्शन में हमारे पास इनपुट और आउटपुट पैरामीटर है, इसलिए यदि आपका पासिंग इनपुट और आउट पैरामीटर समान है तो संदर्भ के आधार पर कॉल का उपयोग करें, अगर इनपुट और आउटपुट पैरामीटर भिन्न हैं, तो मूल्य के आधार पर कॉल का उपयोग करना बेहतर है।

उदाहरण void amount(int account , int deposit , int total )

इनपुट पैरामीटर: खाता, जमा आउटपुट पैरामीटर: कुल

इनपुट और आउट अलग उपयोग कॉल vaule द्वारा है

  1. void amount(int total , int deposit )

इनपुट कुल जमा उत्पादन कुल