दिलचस्प पोस्ट
वेब एपीआई में प्रतिक्रिया को क्रमबद्ध करने में विफल रहा डोनाल्ड बी जॉनसन एल्गोरिदम में मदद, मैं छद्म कोड (भाग द्वितीय) को समझ नहीं सकता मैं सी # में क्लिपबोर्ड सामग्री परिवर्तनों की निगरानी कैसे करूं? कोड के साथ git कॉन्फ़िगरेशन वितरित करना मैं अपने रूटर पर एक एकल दृश्य (एक दृश्य नहीं) कैसे रजिस्टर कर सकता हूं? PHP में एईएस 256 डिक्रिप्शन कैसे करें? यह निर्धारित करने के लिए कि ग्राहक एक स्पर्श डिवाइस है या नहीं PHP SimpleXML – एक्सपेथ नोड हटाएं फेसबुक उपयोगकर्ताओं को कैसे सूचीबद्ध करें, जो एक पृष्ठ या रुचि की तरह इसे बनाने के बाद एक मोंगोज़ में उप-दस्तावेज़ को कैसे पॉप्युलेट करना है? कहाँ "शुद्ध वर्चुअल फ़ंक्शन कॉल" दुर्घटनाओं से आती है? क्या लूपिंग किए बिना तत्व की संख्यात्मक अनुक्रमणिका अपने मूल नोड में प्राप्त करना संभव है? माता-पिता की ऊँचाई को निर्दिष्ट किए बिना माता-पिता के div के 100% बच्चों को कैसे लागू करें? लम्बाई की सूची में आदिम लम्बे की एक सरणी परिवर्तित करें नाम से विधि कॉल करने के लिए प्रतिबिंब का उपयोग कैसे करें

क्या संकलन-योग्यता अनुकूलन के लिए कंपाइलर को अधिक स्थान देती है?

मुझे पता है कि यह पठनीयता में सुधार लाता है और कार्यक्रम को कम त्रुटि प्रवण करता है, लेकिन यह प्रदर्शन में कितना सुधार करता है?

और एक तरफ ध्यान दें, एक संदर्भ और एक const पॉइंटर के बीच का मुख्य अंतर क्या है? मुझे लगता होगा कि उन्हें स्मृति में अलग तरह से संग्रहीत किया जाता है, लेकिन ऐसा कैसे?

धन्यवाद।

वेब के समाधान से एकत्रित समाधान "क्या संकलन-योग्यता अनुकूलन के लिए कंपाइलर को अधिक स्थान देती है?"

[संपादित करें: ठीक है, तो यह सवाल पहले से ज्यादा सोचा था।]

किसी पॉइन्टर-टू-कॉस्ट या सन्दर्भ-संदर्भ का घोषित करने से किसी भी चीज को अनुकूलित करने में किसी भी कंपाइलर की मदद नहीं मिलती। (हालांकि इस उत्तर के नीचे अद्यतन देखें।)

सिर्फ़ घोषणा केवल इंगित करता है कि एक पहचानकर्ता को इसकी घोषणा के दायरे में कैसे उपयोग किया जाएगा; यह नहीं कहता है कि अंतर्निहित ऑब्जेक्ट नहीं बदल सकता।

उदाहरण:

 int foo(const int *p) { int x = *p; bar(x); x = *p; return x; } 

संकलक यह नहीं मान सकता है कि *p को कॉल से bar() संशोधित नहीं किया जाता है, क्योंकि p हो सकता है (जैसे) वैश्विक सूचकांक और bar() लिए एक संकेतक इसे संशोधित कर सकता है।

यदि कंपाइलर को foo() के कॉलर और bar() की सामग्री के बारे में पर्याप्त जानकारी है, जो यह साबित कर सकता है कि bar() *p संशोधित नहीं करता है, तो वह भीड़ घोषणा के बिना यह सबूत भी कर सकता है

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

तो संक्षेप में, इस संदर्भ में सभी const आपको गलतियां करने से रोकता है। यह कंपाइलर को कुछ भी नहीं बताता जो पहले से ही नहीं जानता है, और इसलिए यह अनुकूलन के लिए अप्रासंगिक है।

foo() कॉल करने वाले फ़ंक्शन के बारे में क्या? पसंद:

 int x = 37; foo(&x); printf("%d\n", x); 

कंपाइलर साबित कर सकता है कि यह 37 प्रिंट करता है, क्योंकि foo() एक const int * लेता है?

नहीं। हालांकि foo() एक सूचक-से-कॉन्स्ट लेता है, यह कंस-नेस को दूर कर सकता है और int को संशोधित कर सकता है। (यह अपरिभाषित व्यवहार नहीं है।) फिर से, कंपाइलर सामान्य रूप से कोई मान्यताओं को नहीं बना सकता है; और अगर यह पर्याप्त अनुकूलन करने के लिए foo() बारे में जानता है, तो यह पता चलेगा कि const बिना भी।

एकमात्र समय const ऑप्टीमाइजेशन की तरह इस तरह के मामलों की अनुमति दे सकता है:

 const int x = 37; foo(&x); printf("%d\n", x); 

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

आपके "साइड नोट" प्रश्न का उत्तर देने के लिए, (ए) कॉन्स्ट पॉइंटर एक सूचक है; और (बी) एक कॉन्स्ट पॉइंटर नल के बराबर हो सकता है। आप सही हैं कि आंतरिक प्रतिनिधित्व (यानी एक पता) की संभावना लगभग समान है

[अद्यतन करें]

जैसा क्रिस्टोफ ने टिप्पणी में बताया, मेरा जवाब अधूरा है क्योंकि इसमें restrict नहीं है

C99 मानक के खंड 6.7.3.1 (4) कहते हैं:

बी के प्रत्येक निष्पादन के दौरान, एल को कोई एलवल्यू होना चाहिए जो एल के आधार पर एल है। यदि एल का इस्तेमाल वस्तु एक्स के मूल्य तक पहुंचने के लिए किया जाता है, और एक्स को किसी भी रूप में संशोधित किया जाता है, तो निम्नलिखित आवश्यकताएं लागू होती हैं : टी const-qualified नहीं किया जाएगा …

(यहां बी एक मूल ब्लॉक है, जिस पर पी, एक प्रतिबंधित-सूचक-टू-टी, गुंजाइश है।)

इसलिए यदि सी फ़ंक्शन foo() इस तरह घोषित किया जाता है:

 foo(const int * restrict p) 

… तो संकलक यह मान सकता है कि *p लिए कोई भी बदलाव *p के जीवनकाल के दौरान होते हैं – अर्थात्, foo() के निष्पादन के दौरान – क्योंकि अन्यथा व्यवहार अपरिभाषित होगा।

इसलिए सिद्धांत रूप में, पॉइंटेटर-टू-कंट से restrict करने से ऊपर वाले सभी अनुकूलन को सक्षम कर सकते हैं। क्या कोई कंपलर वास्तव में ऐसे अनुकूलन को लागू करता है, मुझे आश्चर्य है? (जीसीसी 4.5.2, कम से कम, नहीं।)

ध्यान दें कि केवल सी में मौजूद restrict , सी ++ (सी ++ 0x नहीं) में, केवल कंपाइलर-विशिष्ट एक्सटेंशन के रूप में ही मौजूद है।

मेरे सिर के ऊपर से, मैं दो मामलों के बारे में सोच सकता हूं जहां उचित const एक्वालिफिकेशन अतिरिक्त ऑप्टिमाइजेशन की अनुमति देता है (ऐसे मामलों में जहां पूरे प्रोग्राम विश्लेषण अनुपलब्ध है):

 const int foo = 42; bar(&foo); printf("%i", foo); 

यहां, संकलक जानता है कि 42 bar() (जो कैरेंट अनुवाद यूनिट में दिखाई नहीं दे सकता है bar() के शरीर को जांचने के बिना प्रिंट करता है, क्योंकि foo सभी संशोधनों को अवैध है ( यह निमो के उदाहरण के समान है )।

हालांकि, यह भी संभव है कि foo को bar() रूप में घोषित करके const रूप में चिह्नित किया जाए

 extern void bar(const int *restrict p); 

कई मामलों में, प्रोग्रामर को वास्तव में restrict करना चाहिए- गुणनीय पॉइंटर्स-टू-कॉस्ट और सादे पॉइंटर्स-टू-कॉस्ट फ़ंक्शन मापदंडों के रूप में नहीं, क्योंकि केवल पूर्व में पॉइंट टू ऑब्जेक्ट्स की परिवर्तनशीलता के बारे में कोई गारंटी देता है।

आपके प्रश्न के दूसरे भाग के लिए: सभी व्यावहारिक उद्देश्यों के लिए, एक सी ++ संदर्भ को एक निरंतर सूचक के रूप में माना जा सकता है (एक निरंतर मूल्य के लिए सूचक नहीं!) स्वत: अवरोधन के साथ – यह कोई 'सुरक्षित' या 'तेज' नहीं है एक सूचक से, बस अधिक सुविधाजनक

सी ++ में const साथ दो मुद्दे हैं (जहां तक ​​ऑप्टिमाइज़ेशन का संबंध है):

  • const_cast
  • mutable

const_cast मतलब यह है कि भले ही आप किसी संदर्भ को संदर्भित या const पॉइंटर के द्वारा एक ऑब्जेक्ट पास करते हैं, तो फ़ंक्शन const_cast -नेस को दूर कर सकता है और ऑब्जेक्ट को संशोधित कर सकता है (यदि ऑब्जेक्ट से शुरू नहीं होता है तो अनुमति है)

mutable मतलब यह है कि भले ही एक वस्तु const , इसके कुछ हिस्से को संशोधित किया जा सकता है (कैशिंग व्यवहार)। इसके अलावा, वस्तुओं (स्वामित्व के बजाय) की ओर इशारा करते हैं, उन्हें const विधियों में संशोधित किया जा सकता है, भले ही वे तार्किक रूप से ऑब्जेक्ट अवस्था का हिस्सा हो। और अंत में ग्लोबल वैरिएबल भी संशोधित किए जा सकते हैं …

const यहाँ डेवलपर को तार्किक गलतियों को जल्दी से पकड़ने में मदद करने के लिए है

कॉन्स्ट-क्लीटीनेस आम तौर पर प्रदर्शन में मदद नहीं करता है; अधिकांश कंपलर्स फ़ॉरेंट से परे कंसैस्ट को ट्रैक करने के लिए परेशान भी नहीं करते हैं कॉन्सेन्ट के रूप में चर को चिह्नित करना, स्थिति के आधार पर मदद कर सकता है।

संदर्भ और पॉइंटर्स को स्मृति में ठीक उसी तरह से संग्रहीत किया जाता है।

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

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

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

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

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

संदर्भ केवल कार्यान्वयन-वार के नीचे, संकेत दिए गए हैं।

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

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

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

मुझे लगता है कि कॉन्स्ट पॉइंटर संदर्भ के अनुसार वास्तुकला के समान होगा, इसलिए मशीन कोड और दक्षता एक समान होगी। वास्तविक अंतर वाक्यविन्यास है – संदर्भ एक क्लीनर हैं, सिंटैक्स को पढ़ने में आसान है, और जब से आपको एक संकेतक द्वारा प्रदान की गई अतिरिक्त मशीनरी की ज़रूरत नहीं है, तो एक संदर्भ स्टाइलिस्टिक रूप से पसंदीदा होगा