2011-08-03 18 views
7

यदि मेरे पास ऐसा फ़ंक्शन है जो केवल थोड़े समय के लिए मौजूद है, तो रंगों की सूची लगातार एक अंतर बनाती है?क्या फ़ंक्शन के अंदर एक चर के बजाय एक कॉन्स्ट घोषित करने का कोई लाभ है?

string getrandcolor(){ 
    const string colors[5] = {"red", "blue", "green", "yellow", "purple"}; 
    return colors[rand() % 5]; 
} 

नोट: रंग की वास्तविक सूची रंग के सैकड़ों न सिर्फ छोटा सा नमूना मैं पता चला है शामिल है, यकीन नहीं अगर यह एक फर्क तो पड़ता है।

+0

क्या आप अक्सर इस समारोह को कॉल करते हैं? – Cameron

+2

@ टॉमी: स्ट्रिंग को बदले में कॉपी किया गया है, क्योंकि यह रिटर्न-बाय-वैल्यू है। – Cameron

+0

@ कैमरॉन: व्हाउप्स, किसी कारण से मैंने सोचा कि वह एक सूचक वापस कर रहा था। –

उत्तर

16

यह आपको गलती से ओवरराइटिंग चर से रोकता है जिसे आप बदलने का मतलब नहीं था। "ओह!" - सुरक्षा शायद const का सबसे महत्वपूर्ण कार्य है।

हाइपोटेटिक रूप से एक कंपाइलर किसी चर को जानने से कुछ प्रकार का अनुकूलन बदल सकता है, जिसे बदलने के लिए नहीं बदला जाता है, लेकिन मेरे परीक्षण को कभी ऐसा नहीं मिला है जो वास्तव में आपके द्वारा वर्णित स्थिति में कुछ सार्थक करता है।

const static आपके विशेष कोड नमूना में एक महत्वपूर्ण अंतर है। चूंकि आपके रंग [] सरणी स्थानीय हैं, इसलिए प्रत्येक बार getrandcolor() फ़ंक्शन को कॉल करने के लिए इसे फिर से बनाया जाना चाहिए। इसका मतलब यह है कि प्रत्येक बार जब आप getrandcolor() पर कॉल करते हैं तो स्ट्रिंग कन्स्ट्रक्टर पांच बार चला जाता है, जो बहुत ही अपमानजनक है। कॉन्स स्थिर का अर्थ है कि डेटा केवल — बनाया गया है जब पहली बार फ़ंक्शन चलाया जाता है — और साझा मेमोरी स्पेस में डाल दिया जाता है।

+4

'स्थैतिक' की संभावना यहां 'const' से अधिक प्रभाव होने की संभावना है, इसलिए इसका उल्लेख करने के लिए +1। – paxdiablo

+2

"इसे फिर से बनाया जाना चाहिए" मुझे यकीन नहीं है कि यह सच है। यह शायद _will_ होना चाहिए, लेकिन मुझे नहीं लगता कि "यह होना चाहिए" सटीक है। –

+0

यह वास्तव में दिलचस्प धन्यवाद है, हालांकि क्या होगा यदि मैंने चर एक्स और फ़ंक्शन बी के साथ एक अन्य चर के साथ फ़ंक्शन बी किया था और वे दोनों एक ही प्रकार के थे लेकिन उन्हें अलग-अलग माना जाता था, क्या वे एक दूसरे के डेटा का उत्तराधिकारी होंगे ? –

2

यदि आप प्रदर्शन के बारे में बात कर रहे हैं, तो: कोई, इससे कोई फर्क नहीं पड़ता।

2

एक स्थानीय चर एक स्थिरांक की घोषणा करके, आप निम्नलिखित लाभ पाने:

  • शुद्धता: संकलक यह सुनिश्चित करेंगे कि आप गलती से चर का मान नहीं बदलेगा।
  • स्पष्टता: आप स्पष्ट रूप से दस्तावेज करते हैं कि चर स्थिर है।

(वैसे, मुझे यकीन है कि क्या है कि विशिष्ट उदाहरण में स्थिर है नहीं कर रहा हूँ। जल्द ही ...)

+1

स्ट्रिंग स्थिर हैं। 'रंग' 5 स्थिर तारों की 'lvalue सरणी' है। –

+0

मैं बस उस के लिए जाँच कर रहा था :) –

+1

और क्या स्थिर रहेगा? –

5

प्रदर्शन के संदर्भ में? नहीं, शायद नहीं। ऐसा लगता है कि आपकी सरणी static भी हो सकती है, और फिर शायद हाँ

कोड शैली के मामले में? संभवतः। हालांकि const के अतिरिक्त आपके कोड को थोड़ा वर्बोज़ बनाता है, यह भी स्पष्ट करता है कि डेटा को संशोधित नहीं किया जाना है। यह दोनों और सुरक्षित दस्तावेज दोनों है।


आदर्श रूप में, सी ++ में सभी वस्तुओं को डिफ़ॉल्ट रूप से स्थिरांक होगा, और आप mutable लिखने के लिए उन्हें चर बनाने के लिए होगा। यह सब पीछे है!

+5

"आदर्श रूप से, सी ++ में सभी ** चर ** ** डिफ़ॉल्ट रूप से ** const ** होगा" - चलिए इसके बारे में थोड़ा सा सोचें :-) – paxdiablo

+0

@paxdiablo: ऑब्जेक्ट्स। "आदर्श रूप से, सी ++ में सभी चर डिफ़ॉल्ट रूप से _instead_ हो जाएंगे।" चुप रहो। :) –

+0

आदर्श रूप से, "चर" को "नामित वस्तुओं" के रूप में संदर्भित किया जाएगा ;-) –

2

प्रदर्शनों के बारे में बात करते हुए, लेकिन कोड पठनीयता के बारे में बात करते हुए, आपको फ़ंक्शन के बाहर "रंग" चर बनाना चाहिए (क्योंकि एक सौ आकार की सरणी कोड की एक बड़ी मात्रा है, फ़ंक्शन के तर्क को मास्किंग करती है) या तो प्रारंभ में समारोह, या वैश्विक स्तर पर। यदि आप इस चर को निकालने पर विचार नहीं करते हैं, कम से कम, इसे स्थिर बना दें।

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

1

थोड़ा अलग उदाहरण:

const int *global_ptr = 0; 

void bar(); 

void foo() { 
    int x = 1; 
    global_ptr = &x; 
    bar(); 
    std::cout << x << "\n"; 
} 

संकलक क्योंकि सभी यह जानता है के लिए, bar()global_ptr का मूल्य लेता है, int* में बदल देता है, और x को संशोधित करता है के माध्यम से, मूल्य 1 उपयोग करने के लिए अंतिम पंक्ति अनुकूलित नहीं कर सकते यह। यह कुछ हद तक जोखिम भरा कोडिंग होगा, लेकिन एक कॉन्स क्वालीफायर और उत्परिवर्तन कास्टिंग मान्य है, बशर्ते संदर्भ वास्तव में उत्परिवर्तनीय है, इसलिए संकलक को इसके लिए अनुमति देनी चाहिए।

लेकिन, अगर xconst चिह्नित किया गया तो यह स्थिरांक दूर डाली और उत्परिवर्तित को bar() के लिए अमान्य होगा, और इसलिए अनुकूलक माना कि x अभी भी मूल्य 1 जब यह छपा है रखती है नि: शुल्क है।

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

इसके अलावा, लिंक समय अनुकूलन bar inlined किया जाना है, जो मामले में कड़ी समय अनुकूलक और अधिक बारीकी से उसकी सामग्री का निरीक्षण कर सकते अनुमति दे सकते हैं, और बाहर शासन करने में सक्षम हो सकता है।

आपके उदाहरण में, हालांकि, colors का कोई सन्दर्भ अज्ञात कोड से बच सकता है, इसलिए अंतर उत्पन्न नहीं होता है। वैसे भी, एक कॉन्स स्ट्रिंग शायद एक कॉन्स int की तुलना में अनुकूलित करने के लिए कठिन है, इसलिए const का उपयोग करके कुछ शानदार ऑप्टिमाइज़ेशन सक्षम करने के लिए भी कम संभावना है।

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