क्या तर्कों को समय से पहले अनुकूलन के रूप में देखा जा रहा है?


20

"सभी बुराईयो की जड़ समयपूर्व इष्टतमीकरण है"

मुझे लगता है कि हम सभी इस पर सहमत हो सकते हैं। और मैं ऐसा करने से बचने की बहुत कोशिश करता हूं।

लेकिन हाल ही में मैं मान के बजाय कॉन्स्ट रेफरेंस द्वारा मापदंडों को पारित करने के अभ्यास के बारे में सोच रहा हूं । मुझे सिखाया गया है / सीखा गया है कि गैर-तुच्छ फ़ंक्शन तर्क (अर्थात अधिकांश गैर-आदिम प्रकार) को अधिमानतः संदर्भ द्वारा पारित किया जाना चाहिए - मैंने जो कुछ किताबें पढ़ी हैं, वे इसे "सर्वोत्तम अभ्यास" के रूप में सुझाते हैं।

फिर भी मैं मदद नहीं कर सकता, लेकिन आश्चर्य है कि आधुनिक संकलक और नई भाषा सुविधाएँ चमत्कार का काम कर सकती हैं, इसलिए मैंने जो ज्ञान सीखा है वह बहुत अच्छी तरह से पुराना हो सकता है, और मैं वास्तव में कभी भी प्रोफ़ाइल के लिए परेशान नहीं होता हूं यदि कोई प्रदर्शन अंतर हो।

void fooByValue(SomeDataStruct data);   

तथा

void fooByReference(const SomeDataStruct& data);

क्या मैंने जो अभ्यास सीखा है - पासिंग कॉन्स्टेंस रेफ़रेंस (गैर-तुच्छ प्रकारों के लिए डिफ़ॉल्ट रूप से) - समयपूर्व अनुकूलन?


1
यह भी देखें: विभिन्न मानकों से गुजरने वाली रणनीतियों की चर्चा के लिए C ++ कोर दिशानिर्देशों में F.call
अमन


1
@DocBrown उस प्रश्न का स्वीकृत उत्तर कम से कम विस्मयकारी सिद्धांत को संदर्भित करता है , जो यहां भी लागू हो सकता है (यानी कास्ट संदर्भों का उपयोग उद्योग मानक आदि)। उस ने कहा, मैं इस बात से असहमत हूं कि प्रश्न एक डुप्लिकेट है: जिस प्रश्न को आप पूछते हैं कि क्या यह खराब अभ्यास है (आमतौर पर) कंपाइलर अनुकूलन पर निर्भर करता है। यह सवाल उलटा पूछता है: क्या पासिंग कॉन्स्टेंस संदर्भ (समय से पहले) अनुकूलन है?
चारोनएक्स

@CharonX: यदि कोई कंपाइलर ऑप्टिमाइज़ेशन पर भरोसा कर सकता है, तो आपके प्रश्न का उत्तर स्पष्ट रूप से "हाँ, मैन्युअल ऑप्टिमाइज़ेशन आवश्यक नहीं है, यह समय से पहले है"। यदि कोई इस पर भरोसा नहीं कर सकता है (हो सकता है क्योंकि आप पहले से नहीं जानते हैं कि कौन सा संकलक कभी कोड के लिए उपयोग किया जाएगा), तो उत्तर "बड़ी वस्तुओं के लिए है जो शायद समय से पहले नहीं है"। इसलिए, भले ही वे दो प्रश्न वस्तुतः समान नहीं हैं, लेकिन वे IMHO को समान रूप से डुप्लिकेट के रूप में एक साथ जोड़ने के लिए पर्याप्त लगते हैं।
डॉक ब्राउन

1
@DocBrown: तो, इससे पहले कि आप इसे एक ड्यूप घोषित कर सकें, इंगित करें कि प्रश्न में यह कहाँ कहता है कि संकलक को अनुमति दी जाएगी और इसे "अनुकूलित" करने में सक्षम होगा।
डेडुप्लिकेटर

जवाबों:


50

"समयपूर्व अनुकूलन" जल्दी अनुकूलन का उपयोग करने के बारे में नहीं है । यह समस्या को समझने से पहले अनुकूलन के बारे में है, इससे पहले कि रनटाइम को समझा जाए, और अक्सर संदिग्ध परिणामों के लिए कोड को कम पठनीय और कम बनाए रखा जाता है।

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


2
मैं आपके उत्तर के "व्यावहारिक रूप से कोई प्रयास नहीं" भाग पर सहमत हूं। लेकिन समय से पहले अनुकूलन अनुकूलन और सबसे महत्वपूर्ण है अनुकूलन के बारे में उनके एक उल्लेखनीय, मापा प्रदर्शन प्रभाव है। और मुझे नहीं लगता कि अधिकांश C ++ प्रोग्रामर (जिसमें खुद भी शामिल हैं) उपयोग करने से पहले कोई भी माप करते हैं const&, इसलिए मुझे लगता है कि प्रश्न काफी समझदार है।
डॉक ब्राउन

1
आप यह जानने के लिए अनुकूलन करने से पहले मापते हैं कि क्या कोई ट्रेडऑफ़ इसके लायक है। कब्ज और कुल प्रयास के साथ सात अक्षर टाइप कर रहा है, और इसके अन्य फायदे हैं। जब आप पास किए जा रहे चर को संशोधित करने का इरादा नहीं रखते हैं, तो यह गति में सुधार न होने पर भी लाभ का है।
gnasher729

3
मैं सी विशेषज्ञ नहीं हूं, इसलिए एक सवाल: const& fooकहते हैं कि फ़ंक्शन फू को संशोधित नहीं करेगा, इसलिए कॉलर सुरक्षित है। लेकिन एक कॉपी की गई वैल्यू कहती है कि कोई अन्य धागा फू को नहीं बदल सकता है, इसलिए कैली सुरक्षित है। सही? इसलिए, बहु-थ्रेडेड ऐप में, उत्तर शुद्धता पर निर्भर करता है, अनुकूलन पर नहीं।
user949300

1
@DocBrown आप अंततः डेवलपर की प्रेरणा को रोक सकते हैं जिसने कास्ट & डाल दिया है? यदि उन्होंने इसे केवल प्रदर्शन के लिए किया है तो बाकी को ध्यान में रखे बिना इसे समय से पहले अनुकूलन माना जा सकता है। अब अगर वह इसे लगाता है क्योंकि वह जानता है कि यह एक कसौटी पैरामीटर होगा तो वह केवल अपने कोड का स्वयं दस्तावेजीकरण कर रहा है और संकलक को अनुकूलन करने का अवसर दे रहा है, जो बेहतर है।
वालफ्रैट

1
@ user949300: कुछ फ़ंक्शन उनके तर्कों को समवर्ती रूप से या कॉलबैक द्वारा संशोधित करने की अनुमति देते हैं, और वे स्पष्ट रूप से ऐसा कहते हैं।
Deduplicator

16

टीएल; डीआर: कॉन्स्ट रेफरेंस द्वारा पास सी ++ में अभी भी एक अच्छा विचार है, सभी चीजों पर विचार किया गया है। समयपूर्व अनुकूलन नहीं।

TL; DR2: अधिकांश कहावतें समझ में नहीं आतीं, जब तक कि वे ऐसा न करें।


लक्ष्य

यह उत्तर केवल सी ++ कोर दिशानिर्देश (पहले अमोन की टिप्पणी में उल्लिखित) पर लिंक किए गए आइटम को थोड़ा सा विस्तारित करने की कोशिश करता है ।

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


प्रयोज्यता

यह उत्तर केवल फ़ंक्शन कॉल (एक ही थ्रेड पर गैर-वियोज्य नेस्टेड स्कोप) पर लागू होता है।

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


जब मूल्य से गुजरना है

उन मानों के लिए जो अदिश (मानक आदिम हैं जो एक मशीन रजिस्टर के भीतर फिट होते हैं और वैल्यू सिमेंटिक होते हैं) जिनके लिए संचार-बाय-म्यूटेबिलिटी (साझा संदर्भ) की आवश्यकता नहीं है, मान से पास करें।

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


कब संदर्भ से गुजरना है, आदि।

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

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


असामान्य प्रतिमान

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


अनुकूलन पर विचार करने से पहले भाषा विनिर्देश इस उत्तर को कैसे प्रभावित करता है।

उप-टीएल; डीआर एक संदर्भ को प्रचारित करने के लिए कोई कोड नहीं लाना चाहिए; कॉन्स्ट-रेफरेंस से गुजरना इस कसौटी पर खरा उतरता है। हालाँकि, अन्य सभी भाषाएँ इस कसौटी को सहजता से पूरा करती हैं।

(Novice C ++ प्रोग्रामर को सलाह दी जाती है कि वे इस सेक्शन को पूरी तरह से छोड़ दें।)

(इस खंड की शुरुआत आंशिक रूप से gnasher729 के उत्तर से प्रेरित है। हालांकि, एक अलग निष्कर्ष पर पहुंच गया है।)

C ++ उपयोगकर्ता-परिभाषित कॉपी कंस्ट्रक्टर और असाइनमेंट ऑपरेटर की अनुमति देता है।

(यह एक बोल्ड चॉइस है जो कि (और) दोनों अद्भुत और शोचनीय है। यह निश्चित रूप से भाषा डिजाइन में आज के स्वीकार्य मानदंड से भिन्न है।)

यहां तक ​​कि अगर C ++ प्रोग्रामर एक को परिभाषित नहीं करता है, तो C ++ कंपाइलर को भाषा के सिद्धांतों के आधार पर इस तरह के तरीके उत्पन्न करने होंगे, और फिर यह निर्धारित करना होगा कि क्या अतिरिक्त कोड को इसके अलावा निष्पादित करने की आवश्यकता है memcpy। उदाहरण के लिए, एक class/ structजिसमें एक std::vectorसदस्य होता है उसके पास कॉपी-कंस्ट्रक्टर और असाइनमेंट ऑपरेटर होता है जो गैर-तुच्छ होता है।

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

जब कोई संदर्भ या पॉइंटर (कॉन्स्ट रेफरेंस सहित) C ++ (या C) में इधर से उधर हो जाता है, तो प्रोग्रामर को आश्वासन दिया जाता है कि कोई विशेष कोड (उपयोगकर्ता द्वारा परिभाषित या संकलित-जनित कार्य) निष्पादित नहीं किया जाएगा, जो एड्रेस वैल्यू के प्रसार के अलावा है। (संदर्भ या सूचक)। यह व्यवहार की एक स्पष्टता है जो C ++ प्रोग्रामर के साथ सहज है।

हालांकि, पृष्ठभूमि यह है कि सी ++ भाषा अनावश्यक रूप से जटिल है, जैसे कि व्यवहार की यह स्पष्टता एक परमाणु पतन क्षेत्र के आसपास कहीं न कहीं एक नखलिस्तान (एक जीवित निवास स्थान) की तरह है।

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


(ऑफ-टॉपिक सेक्शन) एक आर्टिकल को समर्पित एक सेक्शन, "वांट स्पीड! पास बाई वैल्यू!" लगभग 2009 में लिखा था।

यह लेख 2009 में लिखा गया था और सी ++ में आर-मूल्य के लिए डिजाइन औचित्य की व्याख्या करता है। वह लेख पिछले खंड में मेरे निष्कर्ष के लिए एक वैध प्रतिवाद प्रस्तुत करता है। हालांकि, लेख का कोड उदाहरण और प्रदर्शन का दावा लंबे समय से खारिज कर दिया गया है।

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

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

C ++ में, उपयोगकर्ता दो कार्यान्वयन में से एक को कॉल करने का विकल्प चुन सकता है: बेहतर प्रदर्शन के साथ एक विनाशकारी, या एक सामान्य एक जो इनपुट को संशोधित नहीं करता है। (टेम्पलेट संक्षिप्तता के लिए छोड़ा गया है।)

/*caller specifically passes in input argument destructively*/
std::vector<T> my_sort(std::vector<T>&& input)
{
    std::vector<T> result(std::move(input)); /* destructive move */
    std::sort(result.begin(), result.end()); /* in-place sorting */
    return result; /* return-value optimization (RVO) */
}

/*caller specifically passes in read-only argument*/ 
std::vector<T> my_sort(const std::vector<T>& input)
{
    /* reuse destructive implementation by letting it work on a clone. */
    /* Several things involved; e.g. expiring temporaries as r-value */
    /* return-value optimization, etc. */
    return my_sort(std::vector<T>(input));  
}

/*caller can select which to call, by selecting r-value*/
std::vector<T> v1 = {...};
std::vector<T> v2 = my_sort(v1); /*non-destructive*/
std::vector<T> v3 = my_sort(std::move(v1)); /*v1 is gutted*/    

छांटने के अलावा, यह लालित्य पुनरावर्ती विभाजन द्वारा एक सरणी (आरंभ में अनसोल्ड) में विनाशकारी मध्ययुगीन खोज एल्गोरिथ्म के कार्यान्वयन में भी उपयोगी है।

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


कंपाइलर ऑप्टिमाइज़ेशन इस उत्तर को कैसे प्रभावित करता है

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

हालांकि, अगर निचले स्तर का कार्य कुछ ऐसा है जो विश्लेषण से परे है (जैसे संकलन के बाहर एक अलग पुस्तकालय में कुछ, या कॉल ग्राफ़ जो बहुत जटिल है), तो संकलक को रक्षात्मक रूप से अनुकूलित करना होगा।

मशीन रजिस्टर मूल्य से बड़ी वस्तुओं को स्पष्ट मेमोरी लोड / स्टोर निर्देशों द्वारा या आदरणीय memcpyफ़ंक्शन को कॉल करके कॉपी किया जा सकता है । कुछ प्लेटफार्मों पर, कंपाइलर दो मेमोरी स्थानों के बीच स्थानांतरित करने के लिए SIMD निर्देश उत्पन्न करता है, प्रत्येक निर्देश दसियों बाइट्स (16 या 32) को स्थानांतरित करता है।


वाचालता या दृश्य अव्यवस्था के मुद्दे पर चर्चा

C ++ प्रोग्रामर इसके आदी हैं, जब तक कि प्रोग्रामर C ++ से नफरत नहीं करता है, सोर्स कोड में कॉन्स्ट-रेफरेंस लिखने या पढ़ने का ओवरहेड भयानक नहीं है।

लागत-लाभ विश्लेषण पहले कई बार किया जा सकता है। मुझे नहीं पता कि क्या कोई वैज्ञानिक है जिसे उद्धृत किया जाना चाहिए। मुझे लगता है कि अधिकांश विश्लेषण गैर-वैज्ञानिक या गैर-प्रजनन योग्य होंगे।

यहाँ मैं कल्पना करता हूं (बिना प्रमाण या विश्वसनीय संदर्भ के) ...

  • हां, यह इस भाषा में लिखे सॉफ्टवेयर के प्रदर्शन को प्रभावित करता है।
  • यदि संकलक कोड के उद्देश्य को समझ सकते हैं, तो संभवतः इसे स्वचालित करने के लिए पर्याप्त स्मार्ट हो सकता है
  • दुर्भाग्य से, ऐसी भाषाओं में, जो म्यूटेबिलिटी (कार्यात्मक शुद्धता के विपरीत) के पक्ष में हैं, संकलक म्यूट किए जाने के रूप में अधिकांश चीजों को वर्गीकृत करेगा, इसलिए कब्ज की स्वचालित कटौती गैर-कास्ट के रूप में अधिकांश चीजों को अस्वीकार कर देगी।
  • मानसिक ओवरहेड लोगों पर निर्भर करता है; जो लोग इसे एक उच्च मानसिक ओवरहेड पाते हैं वे व्यवहार्य प्रोग्रामिंग भाषा के रूप में C ++ को अस्वीकार कर देते थे।

यह उन स्थितियों में से एक है जहां मैं चाहता हूं कि मैं केवल एक को चुनने के बजाय दो उत्तर स्वीकार कर
सकूं

8

डोनाल्डKnuth के पेपर "स्ट्रक्चर्डप्रोग्रामिंगविथगोसटॉस्टेट्स" में, उन्होंने लिखा: "प्रोग्रामर समय के बारे में सोचने या चिंता करने में बहुत समय बर्बाद करते हैं, अपने कार्यक्रमों के गैर-राजनीतिक हिस्सों की गति, और दक्षता पर इन प्रयासों का वास्तव में एक मजबूत नकारात्मक प्रभाव पड़ता है जब डिबगिंग और रखरखाव पर विचार किया जाता है। हमें छोटी क्षमताओं के बारे में भूलना चाहिए, समय के 97% के बारे में कहना चाहिए: समय से पहले अनुकूलन सभी बुराई की जड़ है। फिर भी हमें उस महत्वपूर्ण 3% में अपने अवसरों को पारित नहीं करना चाहिए। " - समय से पहले अनुकूलन

यह प्रोग्रामर को उपलब्ध सबसे धीमी तकनीकों का उपयोग करने की सलाह नहीं दे रहा है। यह कार्यक्रम लिखते समय स्पष्टता पर ध्यान केंद्रित करने के बारे में है । अक्सर, स्पष्टता और दक्षता एक व्यापार बंद है: यदि आपको केवल एक चुनना चाहिए, तो स्पष्टता चुनें। लेकिन अगर आप दोनों को आसानी से हासिल कर सकते हैं, तो दक्षता से बचने के लिए स्पष्टता (जैसे संकेत देना कि कुछ स्थिर है) को अपंग करने की कोई आवश्यकता नहीं है।


3
"यदि आपको केवल एक ही चुनना चाहिए, तो स्पष्टता चुनें।" इसके बजाय दूसरे को प्राथमिकता दी जानी चाहिए , क्योंकि आप दूसरे को चुनने के लिए मजबूर हो सकते हैं।
डेडुप्लिकेटर

@Deduplicator धन्यवाद। ओपी के संदर्भ में, हालांकि, प्रोग्रामर को चुनने की स्वतंत्रता है।
लॉरेंस

आपका उत्तर इससे कुछ अधिक सामान्य है, हालांकि ...
Deduplicator

@ डेडप्लिकेटर आह, लेकिन मेरे उत्तर का संदर्भ (भी) है जिसे प्रोग्रामर चुनता है। यदि प्रोग्रामर पर पसंद को मजबूर किया गया था, तो यह "आप" नहीं होगा जो उठाता है :)। मैंने आपके द्वारा सुझाए गए परिवर्तन पर विचार किया और अपने उत्तर को तदनुसार संपादित करने पर आपत्ति नहीं जताई, लेकिन मैं इसकी स्पष्टता के लिए मौजूदा शब्दों को प्राथमिकता देता हूं।
लॉरेंस

7

([Const] [rvalue] संदर्भ) द्वारा पास करना (मान) इंटरफ़ेस द्वारा किए गए इरादे और वादों के बारे में होना चाहिए। इसका प्रदर्शन से कोई लेना-देना नहीं है।

रिक्की के अंगूठे का नियम:

void foo(X x);          // I intend to own the x you gave me, whether by copy, move or direct initialisation on the call stack.     

void foo(X&& x);        // I intend to steal x from you. Do not use it other than to re-assign to it after calling me.

void foo(X const& x);   // I guarantee not to change your x

void foo(X& x);         // I may modify your x and I will leave it in a defined state

3

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.