2012-03-11 14 views
11

मुझे गोली मार मत करो, लेकिन यह पहली बार मैं एक स्थानीय लिखने योग्यconst के उपयोग देखा है (या हो सकता है मैं कर रहा हूँ अभी जिस तरह भी बूढ़ा ...): "The WinAPI way (by Peter Below from TeamB)"लिखने योग्य स्थानीय स्थिरांक

एक ले लो स्थानीय कॉन्स FullScreen: Boolean = False; और फिर FullScreen := not FullScreen;

पहले मैं thoght यह आधुनिक डेल्फी संस्करणों के साथ एक नई सुविधा थी, लेकिन यह मेरे डी 5 के साथ भी काम करता है। तो मेरा सवाल यह है: क्या वैश्विक लेखन योग्य स्थिरांक एक ही वैश्विक लेखन योग्य निरंतर घोषित करने के समान हैं?

उदा।

procedure TForm1.Button1Click(Sender: TObject); 
Const 
    LocalConst: Boolean = False; 
begin 
    LocalConst := not LocalConst; 
    if LocalConst then Beep; 
end; 

इस कोड की तरह ही काम करता है? :

Const 
    GlobalConst_Button2Click: Boolean = False; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
    GlobalConst_Button2Click := not GlobalConst_Button2Click; 
    if GlobalConst_Button2Click then Beep; 
end; 

या, LocalConst इसकी विधि के लिए स्थानीय है यानी स्थिर? क्या यह निरंतर थ्रेड सुरक्षित है?
क्या कोई इस मुद्दे पर कुछ प्रकाश डाल सकता है?

+6

@ user539484 - गुमनाम रूप से नीचे हटना बंद करें; मुझे यकीन है कि यह तुम हो! मैं आपका वोट कास्ट देख रहा हूं। – TLama

उत्तर

11

स्थानीय और वैश्विक टाइप किए गए स्थिरांक वाला कोड बिल्कुल वही काम करता है।

जैसा कि डेविड ने पहले ही कहा है कि वैश्विक स्थिर चर (उर्फ टाइप स्थिर) पूरे कार्यक्रम में पहुंच योग्य है और स्थानीय स्थैतिक var नहीं है। नीचे मैं typed constants को static variables के रूप में संदर्भित करूँगा क्योंकि यह वास्तव में वे हैं।

हालांकि स्थानीय स्थैतिक चर वैश्विक स्मृति वैर के समान ही स्मृति में जारी रहता है। यह केवल संकलक है जो आपको नियमित रूप से बाहर से स्थानीय वैर तक पहुंचने की अनुमति नहीं देता है।
यह भी ध्यान रखें कि यदि आपका स्थानीय स्थैतिक var विशेष रूप से बड़ा है (या आपके पास उनमें से बहुत से हैं) तो वे मेमोरी का निरंतर हिस्सा खाएंगे (भले ही मैं किसी परिदृश्य की कल्पना नहीं कर सकता जहां यह समस्या हो सकती है)

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

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

कम
थ्रेडेड कोड में स्थिर वार्स का उपयोग करने में एक बहुत बुरा विचार है जब तक आप जानते हैं कि वास्तव में आप क्या कर रहे हैं है।

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

आप धागे के बीच डाटा साझा करने के लिए यह threadvar,
देखें उपयोग करने के लिए एक बेहतर विचार है चाहते हैं: http://en.wikipedia.org/wiki/Thread-local_storage
और: https://stackoverflow.com/search?q=delphi+threadvar

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

4

क्या स्थानीय लिखने योग्य स्थिरांक वैश्विक लेखन योग्य निरंतर घोषित करने के समान हैं?

केवल अंतर ही दायरा है। वैश्विक चर, अच्छी तरह से, वैश्विक, और स्थानीय चर के स्थानीय दायरे है। लिखने योग्य टाइप किए गए स्थिरांक सी स्थिर स्थानीय चर के लिए एक उचित अनुमान हैं।

लिखने योग्य टाइप किए गए स्थिरांक का भारी नुकसान यह है कि सी में कोई कीवर्ड समर्थन नहीं है और आपको भाषा के अर्थ को टॉगल करने के लिए एक कंपाइलर विकल्प का उपयोग करना होगा! मेरे विचार में यह लेखन योग्य टाइप किए गए स्थिरांक प्रभावी ढंग से बेकार बनाता है।

+10

100k प्रतिनिधि तक पहुंचने पर बधाई! मुझे लगता है कि यही कारण है कि आपको फूल मिल गए! –

+0

बहुत बुरा इस जवाब का मूल संस्करण गलत था। लेकिन धन्यवाद! –

+0

@ डेविड, मत भूलें * किसने * 100k बनाया! : -पी बधाई हो! – kobik

4

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

सबसे पहले, जैसा कि जोहान और डेविड ने कहा कि वैश्विक और स्थानीय स्थिरांक स्मृति में भिन्न नहीं हैं।

लिखने योग्य स्थिरांक के उपयोग में रुचि रखने वालों के लिए: मुझे यह कार्य "आलसी" बनाने के लिए "वादा" कार्यक्षमता अनुकरण करने के लिए उपयोगी पाया गया। संभोग डेल्फी वादे का समर्थन नहीं करता है, इसलिए यह केवल आंशिक रूप से कुशल है।

एक समारोह एक स्ट्रिंग में शब्दों की राशि की गणना करने के विचार करें:

function CountWords(Input: String):Integer; 
var 
    Worker: TStringList; 
begin 
    Worker := TStringList.Create; 
    Worker.DelimitedText := Input; 
    Result := Worker.Count; 
    Worker.Free; 
end; 

अब कल्पना यह हमारे कार्यक्रम में कई बार कहा जाता है beeing। TStringList ऑब्जेक्ट बनाया जाएगा और प्रत्येक बार जब हम ऐसा करते हैं तो अतिरिक्त नौकरी कर रहे हैं। आप बेशक, एक वैश्विक चर Worker_CountWords बनाने के द्वारा इस का समाधान कर सकता कार्यक्रम प्रारंभ होने पर यह प्रारंभ करें और अपने समारोह में इसका इस्तेमाल करते हैं, लेकिन इस पर एक नज़र डालें:

function CountWords(Input: String):Integer; 
{$J+} //Enable writable constants 
const 
    Worker: TStringList = nil; 
{$J-} //Disable writable constants 
begin 
    if Worker = nil then 
    begin 
    Worker := TStringList.Create; 
    //Other Initialization code here 
    end; 
    Worker.DelimitedText := Input; 
    Result := Worker.Count; 
end; 

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

procedure DoSomeWork; 
const 
    FirstCall : TDateTime = 0; 
begin 
    if FirstCall = 0 then 
    PDateTime(@FirstCall)^ := Now; 
    Writeln(TimeToStr(FirstCall)); 
    //some actual work here 
end; 

यही बात कार्यों में const मापदंडों पर लागू होता है, क्योंकि वे कर रहे हैं,:

इसके अलावा यह आप भी कुछ इस तरह कर सकता है क्रम निरंतर मूल्यों को संशोधित करने में {$ WRITABLECONST पर} के लिए आवश्यक नहीं है, var पैरामीटर के समान बिल्कुल (भिन्न चर बनाने पर समय बिताने से बचने के संदर्भ में पारित), केवल अंतर यह है कि कंपाइलर आपको इन मानों को सामान्य रूप से बदलने की अनुमति नहीं देता है।

पीएस स्थिरांक समारोह मानकों के साथ सावधान रहो, जब से तुम foo(12) की तरह वास्तविक स्थिरांक गुजरती हैं और है कि कर सकता है शायद गंदगी कुछ को संशोधित करने की कोशिश कर सकते हैं ...

+0

'सिंगलटन' फ़ंक्शन एक सिंगलटन का उपयोग करके फ़ंक्शन में कार्यक्षमता में कैसे भिन्न होता है? –

+2

'फर्स्टकॉल: टीडीएटीटाइम' के साथ '{$ J-} ​​' – kobik

+0

के साथ अच्छी चाल है, मुझे लगता है कि {$ J दृष्टिकोण का उपयोग करना बेहतर है। यह कंपाइलर चेतावनियों के साथ काम करता है। जब डेल्फी को स्थाई मेमोरी का इरादा होता है तो मैं डेल्फी को कॉन्स/var को प्रतिस्थापित करने के लिए स्थैतिक जैसे उचित कीवर्ड प्राप्त करना पसंद करूंगा। यहां तक ​​कि कंपाइलर निर्देश भी थोड़ा गन्दा हैं। –

0

मैं पूरी तरह से सवाल समझ में नहीं आया, तो मैं सभी मामलों का जवाब देंगे कि सका होते हैं:

  1. आप समझ में नहीं आया, तो कैसे मेरे CountWords उदाहरण के 2 अलग: सबसे पहले एक बनाता है और वर्ग उदाहरण हर बार यह कहा जाता है मुक्त करता है। दूसरा, केवल प्रथम कॉल पर क्लास इंस्टेंस बनाता है, फिर प्रोग्राम समाप्त होने तक इसका उपयोग करता है।
  2. यदि आपका मतलब है कि यदि आपने सिंगलटन बनाया है और इसमें CountWords लागू किया है तो यह अलग होगा: यह कार्यक्षमता में भिन्न नहीं होगा, लेकिन आपको इसके लिए एक पूरी नई कक्षा लिखनी होगी, फिर इसे प्रोग्राम शुरू करने और उपयोग पर प्रारंभ करना होगा बाद में। इसके अलावा सिंगलेट्स का उपयोग करने पर बहुत आलोचना है (अधिक जानकारी के लिए विकी देखें), इसलिए मैं ऐसा नहीं करूँगा।
  3. यदि आप वास्तविक काम के बारे में पूछ रहे हैं तो ये दो उदाहरण कार्य निष्पादित कर रहे हैं: वे स्पष्ट रूप से समान परिणाम प्राप्त करते हैं, लेकिन पहले वातावरण को चलाने के लिए अनुकूलित नहीं किया जाता है जो इस फ़ंक्शन को बहुत कुछ कहता है। जैसा कि मैंने पहले कहा था, आप एक वैश्विक चर घोषित करके एक ही परिणाम तक पहुंच सकते हैं, लेकिन यदि आप ऐसा करते हैं - तो आप अपने कार्यक्रम में हर जगह अपना ग्लोबल वैरिएबल देखेंगे, जबकि इसे केवल एक विशिष्ट स्थान में और कहीं और नहीं चाहिए।

पीएस मैं वास्तव में const फ़ंक्शन पैरामीटर के बारे में गलत था, यह पता चला कि ये चीजें विभिन्न डेल्फी संस्करणों में अलग-अलग व्यवहार करती हैं। कॉन्स पैरामीटर डेल्फी 6 में var पैरामीटर के समान ही काम करते थे, लेकिन डेल्फी XE2 में ऐसा लगता है कि स्थानीय चर किसी भी तरह से बनाया गया है। किसी भी तरह से मैं const फ़ंक्शन पैरामीटर के साथ गड़बड़ करने की अनुशंसा नहीं करता हूं।

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