दिलचस्प पोस्ट
सब कुछ लेकिन विशिष्ट निर्देशिकाओं को अनदेखा करने के लिए .gitignore का उपयोग करना आप गतिशील लोड किए गए जावास्क्रिप्ट ब्लॉक को कैसे निष्पादित करते हैं? कंसोल पर यह जावास्क्रिप्ट कोड प्रिंट "अपरिभाषित" क्यों करता है? डी 3 v4 – शून्य की संपत्ति पाठ पढ़ा नहीं जा सकता jQuery में Greasemonkey 1.0 jQuery का उपयोग कर वेबसाइटों के साथ संघर्ष स्विफ्ट में NSObject उपवर्ग: हैश बनाम हैश वैल्यू, है एक्वाल बनाम == वेबब्राउजर नियंत्रण के उपयोगकर्ता एजेंट को बदलना JSON को HTML के रूप में प्रदर्शित करें MySQL में चल रहे कुल की गणना करें तारीख के बीच mysql क्वेरी का चयन करें? "अपरिवर्तनीय प्रकार: int () <str ()" '$ (यह)' की लागत क्या है? सी + + और सी के संयोजन – कैसे # efdef __cplusplus काम करता है? "अवैध निर्देश: 4" त्रुटि क्या है और "-मॅकोक्स-वर्जन-मिन = 10.x" क्यों ठीक है? अक्षांश / लैन निर्देशांक के 2 सूचियों के बीच भौगोलिक दूरी

स्थिर और कम्पाइलर अनुकूलन सी ++ में

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

उदाहरण के लिए, कम्पाइलर एक ऐसी विधि का अनुकूलन कैसे करता है जिसे const बनाम बना दिया जाता है, लेकिन यह नहीं होना चाहिए क्या होता है जब आप अचल परिवर्तनों को लागू करते हैं? क्या वे const विधियों के इन अनुकूलन को प्रभावित करते हैं?

वेब के समाधान से एकत्रित समाधान "स्थिर और कम्पाइलर अनुकूलन सी ++ में"

चलो तरीकों की उपेक्षा और केवल const वस्तुओं में देखो; संकलक के अनुकूलन के लिए यहां बहुत अधिक अवसर हैं। यदि कोई वस्तु const घोषित की जाती है, तो (आईएसओ / आईईसी 14882: 2003 7.1.5.1 (4)):

सिवाय इसके कि किसी भी वर्ग के सदस्य घोषित किए गए परिवर्तन (7.1.1) को संशोधित किया जा सकता है, अपने जीवनकाल (3.8) के दौरान एक const वस्तु को संशोधित करने का कोई भी प्रयास अपरिभाषित व्यवहार में परिणाम देता है।

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

  • ऑब्जेक्ट का मान सीधे मशीन अनुदेश ऑप्लोड में शामिल करना
  • कोड का पूरा उन्मूलन, जिसे कभी नहीं पहुंचा जा सकता है क्योंकि कॉन्से ऑब्जेक्ट एक सशर्त अभिव्यक्ति में उपयोग किया जाता है जो कि समय संकलन में ज्ञात होता है
  • लूप अनारोल हो रहा है यदि const वस्तु एक पाश के पुनरावृत्तियों की संख्या को नियंत्रित कर रहा है

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

व्यवहार में, मुझे नहीं लगता है कि वहाँ ऐसे कंपाइलर होते हैं जो सभी प्रकार की const वस्तुओं के लिए कोई महत्वपूर्ण अनुकूलन करते हैं। लेकिन वस्तुओं के लिए जो आदिम प्रकार हैं (ints, chars, आदि) मुझे लगता है कि compilers उन वस्तुओं के उपयोग के अनुकूलन में काफी आक्रामक हो सकता है

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

GotW # 81 लेख में हर्ब सटर, बहुत अच्छी तरह से बताता है कि संकलक किसी भी संदर्भ को संदर्भित नहीं कर सकता है, या जब कंसल्टेंट रिटर्न वेल्यू घोषित करता है। इसका कारण यह है कि कंपाइलर को यह सुनिश्चित करने का कोई तरीका नहीं है कि संदर्भित ऑब्जेक्ट को बदला नहीं जाएगा, भले ही घोषित कॉन्स्ट: कोई भी const_cast का उपयोग कर सकता है, या किसी अन्य कोड में एक ही ऑब्जेक्ट पर गैर-कॉन्स्ट संदर्भ हो सकता है।

हालांकि, हर्ब Sutter के लेख का हवाला देते हुए:

ऐसा केवल एक ही मामला है जहां "const" कहने का मतलब वास्तव में कुछ हो सकता है, और वह तब होता है जब वस्तुओं को परिभाषित किया जाता है उस बिंदु पर const बनाया जाता है उस स्थिति में, संकलक अक्सर सफलतापूर्वक ऐसे "वास्तव में कस्ट" ऑब्जेक्ट को केवल-पढ़ने वाली मेमोरी में डाल सकता है […]

इस लेख में बहुत अधिक है, इसलिए मैं इसे पढ़ने से आपको प्रोत्साहित करता हूं: इसके बाद आपको लगातार अनुकूलन की बेहतर समझ होगी।

हैंडविटिंग शुरू होता है

अनिवार्य रूप से, पहले से डेटा तय हो गया है, अधिक संकलक डेटा के वास्तविक असाइनमेंट के चारों ओर स्थानांतरित कर सकता है, यह सुनिश्चित कर सकता है कि पाइप लाइन बाहर नहीं निकलती है

अंत हैंडविविंग

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

उसमें जोड़ा गया, संकलक आपको यह सच कहकर भरोसा नहीं कर सकता – आप एक पुस्तकालय समारोह के अंदर const को दूर कर सकते हैं, जिस बारे में यह नहीं पता है।

तो हां, कॉन्स्ट-अचुरता एक उद्देश्य योग्य चीज है, लेकिन यह कंपाइलर को कुछ भी नहीं बताता है जो इसे अपने लिए समझ नहीं पाएगा, एक अच्छा अनुकूलन संकलक मान रहा है।

यह कंसोल घोषित समारोह को अनुकूलित नहीं करता है

यह फ़ंक्शन को ऑप्टिमाइज़ कर सकता है जो कंस घोषित किए जाने वाले फ़ंक्शन को कॉल करता है

 void someType::somefunc(); void MyFunc() { someType A(4); // Fling(A.m_val); A.someFunc(); Flong(A.m_val); } 

यहाँ फ़्लिंग को कॉल करने के लिए, valud A.m_val को सीपीयू रजिस्टर में लोड करना पड़ा। यदि कुछ फंक () कॉन्स्ट नहीं है, तो फ़्लॉन्ग () को कॉल करने से पहले मूल्य पुनः लोड करना होगा। यदि कुछ फ़ंक कॉन्क है, तो हम फ्लोंग को उस मूल्य के साथ कॉल कर सकते हैं जो अब भी रजिस्टर में है।

कॉन्स्ट के रूप में तरीकों का मुख्य कारण कॉन्स्ट की सहीता के लिए है, विधि के स्वयं के संभावित संकलन अनुकूलन के लिए नहीं।

यदि चर const हैं वे (सिद्धांत में) अनुकूलित हो सकते हैं लेकिन केवल यह है कि कंपाइलर द्वारा दायरे को देखा जा सकता है। सभी कंपाइलर के लिए उन्हें अन्यत्र एक const_cast के साथ संशोधित करने की अनुमति देने के बाद

ये सभी सच्चे उत्तर हैं, लेकिन जवाब और सवाल एक बात मानते हैं: संकलक ऑप्टिमाइज़ेशन वास्तव में मायने रखता है।

केवल एक प्रकार का कोड है जहां संकलक ऑप्टिमाइज़ेशन मायने रखता है, जो कोड में है

  • एक तंग भीतरी लूप,
  • कोड में जो आप संकलित करते हैं, जैसा कि एक तृतीय-पक्ष लायब्रेरी के विपरीत है,
  • फ़ंक्शन या विधि कॉल (यहां तक ​​कि छिपे हुए वाले) नहीं हैं,
  • जहां कार्यक्रम काउंटर अपने समय का एक उल्लेखनीय अंश खर्च करता है

यदि अन्य 99% कोड एन.ए. डिग्री से अनुकूलित है, तो यह अंतर का झुंझलाहट नहीं करेगा, क्योंकि यह केवल कोड में महत्वपूर्ण है, जहां प्रोग्राम काउंटर वास्तव में समय बिताता है (जिसे आप नमूना करके पा सकते हैं)।

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

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

सबसे स्पष्ट बिंदु जहां const एक सीधा अनुकूलन है एक समारोह में तर्कों को पारित कर रहा है। यह सुनिश्चित करना अक्सर महत्वपूर्ण होता है कि फ़ंक्शन डेटा को संशोधित नहीं करता है, इसलिए फ़ंक्शन हस्ताक्षर के लिए केवल वास्तविक विकल्प ये हैं:

 void f(Type dont_modify); // or void f(Type const& dont_modify); 

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

/ संपादित करें: वास्तव में, एक अच्छा संकलक फ़ंक्शन के नियंत्रण प्रवाह का विश्लेषण कर सकता है, यह निर्धारित करता है कि यह तर्क को संशोधित नहीं करता है और ऑप्टिमाइज़ेशन (एक प्रतिलिपि के बजाय किसी संदर्भ को पारित करने) ही करता है const यहाँ संकलक के लिए केवल एक मदद है। हालांकि, चूंकि सी ++ में कुछ बहुत ही जटिल शब्दार्थ हैं और बड़े नियंत्रण के लिए इस तरह का नियंत्रण प्रवाह विश्लेषण बहुत महंगा हो सकता है, इसलिए हमें इसके लिए कंपाइलर पर भरोसा नहीं करना चाहिए। क्या किसी के पास मेरे पीछे कोई डेटा है / मुझे गलत साबित करना है?

/ EDIT2: और हाँ, जैसे ही कस्टम प्रतिलिपि कंसल्टेंट्स खेलने के लिए आते हैं, यह बहुत मुश्किल हो जाता है क्योंकि दुर्भाग्यवश उन्हें इस स्थिति में कॉल करने की अनुमति नहीं है।

यह कोड,

 class Test { public: Test (int value) : m_value (value) { } void SetValue (int value) const { const_cast <Test&>(*this).MySetValue (value); } int Value () const { return m_value; } private: void MySetValue (int value) { m_value = value; } int m_value; }; void modify (const Test &test, int value) { test.SetValue (value); } void main () { const Test test (100); cout << test.Value () << endl; modify (test, 50); cout << test.Value () << endl; } 

आउटपुट:

 100 50 

जिसका अर्थ है कि const घोषित ऑब्जेक्ट एक कॉन्स्ट सदस्य फ़ंक्शन में बदल दिया गया है। सी ++ भाषा में const_cast (और म्यूटिव कीवर्ड) की उपस्थिति का मतलब है कि कस्ट कीवर्ड कंपाइलर को अनुकूलित कोड बनाने में सहयोग नहीं कर सकता। और जैसा कि मैंने पिछली पोस्ट में बताया था, यह अप्रत्याशित परिणाम भी उत्पन्न कर सकता है।

एक सामान्य नियम के रूप में:

const! = अनुकूलन

वास्तव में, यह एक कानूनी सी ++ संशोधक है:

 volatile const 

const मदद करता है कम्पाइलर का अनुकूलन मुख्य रूप से क्योंकि यह आपको अनुकूलन कोड लिखता है जब तक आप const_cast में फेंक न दें