2011-10-01 30 views
8

क्या स्मृति में आवंटित किए बिना केवल रनटाइम पर उपलब्ध जानकारी का उपयोग करते हुए डी में string बनाने के लिए कोई प्रकार का तरीका है?स्मृति आवंटित किए बिना डी में स्ट्रिंग बनाना?

मुझे क्या करना चाहते हो सकता है की एक साधारण उदाहरण:

void renderText(string text) { ... } 

void renderScore(int score) 
{ 
    char[16] text; 
    int n = sprintf(text.ptr, "Score: %d", score); 
    renderText(text[0..n]); // ERROR 
} 

इस का उपयोग करके आप क्योंकि text का टुकड़ा अपरिवर्तनीय नहीं है कोई त्रुटि मिलती हैं, और इसलिए है नहीं एक string (यानी immutable(char)[])

मैं केवल इस के आसपास के तीन तरीके के बारे में सोच सकते हैं:

  1. कास्ट एक string को टुकड़ा। यह काम करता है, लेकिन बदसूरत है।
  2. स्लाइस का उपयोग करके एक नई स्ट्रिंग आवंटित करें। यह काम करता है, लेकिन मुझे स्मृति आवंटित करने की आवश्यकता नहीं है।
  3. renderTextconst(char)[] लेने के लिए बदलें। यह यहां काम करता है, लेकिन (ए) यह बदसूरत है, और (बी) फोबोस में कई कार्यों की आवश्यकता string है, इसलिए यदि मैं उन तरीकों से उसी तरह उपयोग करना चाहता हूं तो यह काम नहीं करता है।

इनमें से कोई भी विशेष रूप से अच्छा नहीं है। क्या मैं कुछ भूल रहा हूँ? इस समस्या के आसपास हर कोई कैसे मिलता है?

+1

हेरेसी, पाखंडी! 'Snprintf' का प्रयोग करें! : डी – BCS

+2

मुझे लगता है कि # 3 वास्तव में सही समाधान है। स्ट्रिंग -> अपरिवर्तनीय (char) [] का अर्थ है कि डेटा नहीं बदला जा सकता है (जब तक कि यह अभी भी कहीं भी संदर्भित है, अन्यथा जीसी इसे इकट्ठा करने की अनुमति है, AFAIK)। मुझे नहीं लगता कि आप कभी भी स्टैक-आवंटित डेटा के लिए ऐसी गारंटी दे सकते हैं। लेकिन जब तक रेंडर टेक्स्ट को वास्तव में कहीं भी टेक्स्ट स्टोर करने की आवश्यकता नहीं होती है, तो इसे कॉन्स (char) [] का उपयोग करना चाहिए। चूंकि अपरिवर्तनीय स्थिरता से मजबूत है, इसे केवल तभी उपयोग किया जाना चाहिए जब आवश्यक हो। मैं सहमत हूं, हालांकि फोबोस में कई फ़ंक्शन अस्थिर रूप से कॉन्स्ट (char) [] के बजाय स्ट्रिंग लेते हैं, जिन्हें फ़ोबोस में ठीक किया जाना चाहिए। – jpf

+0

@jpf: मैं 100% सहमत हूं। –

उत्तर

2

assumeUnique std.exception जोनाथन के उत्तर से देखें।

+0

यह मानने के साथ कैसे बातचीत करेगा अनन्य एक रेफरी तर्क ले रहा है (इस मामले में एक टुकड़ा अभिव्यक्ति जो आईआईआरसी आर-वैल्यू नहीं है)? – BCS

+0

मुझे लगता है कि स्टैक आवंटित स्थान के साथ assumeUnique का उपयोग मान्य नहीं है। स्टैक स्पेस अद्वितीय नहीं है, जब रेंडरस्कोर वापस आ गया है और दूसरा फ़ंक्शन कहा जाता है, तो यह स्टैक पर उसी स्थान का पुन: उपयोग कर सकता है। -> अद्वितीय नहीं है और __not अपरिवर्तनीय__ भी नहीं है। याद रखें कि अपरिवर्तनीय रूप से भी अर्थपूर्ण रूप से साझा किया गया है: क्या आप वास्तव में चाहते हैं कि कोड आवंटित डेटा को किसी अन्य थ्रेड पर पास करने में सक्षम हो? – jpf

+0

आपको करना होगा: 'auto text2 = text [0..n]; renderText (assumeUnique (text2)); हालांकि जेपीएफ कहता है, यह बहुत बुरा है क्योंकि आपके पास अभी भी 'टेक्स्ट' तक पहुंच है, जो' अपरिवर्तनीय 'के उद्देश्य को हरा देता है। –

0

नहीं, आप नहीं बना कर सकते हैं एक स्ट्रिंग आवंटन बिना। क्या आपका मतलब पहुंच? आवंटन से बचने के लिए, आपको या तो पहले बनाई गई स्ट्रिंग तक पहुंचने के लिए स्लाइस या पॉइंटर का उपयोग करना होगा। हालांकि कलाकारों के बारे में निश्चित नहीं है, यह नई स्ट्रिंग के लिए नई मेमोरी स्पेस आवंटित या नहीं कर सकता है।

+0

ओपी स्टैक आवंटन का उपयोग करने के लिए तैयार है, इसलिए मुझे लगता है कि वह केवल ढेर आवंटन से बचने की कोशिश कर रहा है। – BCS

0

एक तरीका यह चारों ओर पाने के लिए एक नया अपरिवर्तनीय संस्करण में परिवर्तनशील वर्ण कॉपी करने के लिए किया जाएगा तो काट कि:

void renderScore(int score) 
{ 
    char[16] text; 
    int n = sprintf(text.ptr, "Score: %d", score); 
    immutable(char)[16] itext = text; 
    renderText(itext[0..n]); 
} 
हालांकि

:

  1. डीएमडी वर्तमान में करने के लिए इस वजह से की अनुमति नहीं है एक दोष।
  2. आप एक अनावश्यक प्रतिलिपि बना रहे हैं (एक जीसी आवंटन से बेहतर है, लेकिन अभी भी महान नहीं है)।
+0

क्या आप वाकई काम करना चाहिए? उद्धरण टीडीपीएल: "पत्थर में एक अपरिवर्तनीय मूल्य डाला जाता है: ... यह कार्यक्रम के निष्पादन में कभी नहीं बदलेगा"। मैं अभी भी इस आवश्यकता का तर्क दूंगा कि __never__ स्टैक-आवंटित डेटा के लिए मिले।यह स्थानीय चर के लिए काम कर सकता है, लेकिन केवल तभी जब उन्हें संकलित समय पर प्रारंभ किया जाता है ताकि उन्हें ढेर के बजाय स्थिर डेटा सेगमेंट में रखा जा सके। लेकिन आपके उदाहरण को अभी भी रनटाइम पर सेट करना है -> स्टैक स्पेस। – jpf

+0

@jpf: अपरिवर्तनीयता और जीवनकाल ऑर्थोगोनल मुद्दे हैं। अपरिवर्तनीयता गारंटी देता है कि यह अपने जीवनकाल के दौरान नहीं बदलेगा, लेकिन अनंत जीवनकाल की गारंटी नहीं देता है। यदि आप सीमित जीवनकाल के साथ कुछ संदर्भित करते हैं तो यह सुनिश्चित करने के लिए आप पर निर्भर है कि आप इसे विच्छेदन से परे उपयोग न करें। –

+0

ऐसा लगता है कि आप सही हैं। टीडीपीएल थोड़ा असंगत है, यह स्पष्ट रूप से कहता है "जैसे ही इसे शुरू किया गया है, आप यह भी मान सकते हैं कि इसे हमेशा संग्रहीत स्मृति में जला दिया गया है। यह कभी भी __program__ के निष्पादन में कभी नहीं बदलेगा", जो इमो अनंत जीवनकाल का भी अर्थ है। लेकिन पृष्ठ 401 पर यह कहता है "एक अपरिवर्तनीय मूल्य गारंटी है कि पूरे __its__ जीवन भर में कभी भी बदलाव न करें" – jpf

6

आपके पास char की स्थिर सरणी है। आप इसे उस फ़ंक्शन में पास करना चाहते हैं जो immutable(char)[] लेता है। केवल ऐसा करने के लिए बिना किसी भी आवंटन के तरीके को कास्ट करना है। इसके बारे में सोचो। आप जो चाहते हैं वह एक प्रकार है जैसे कि यह एक और है। यही वह कास्टिंग करता है। आप इसे करने के लिए assumeUnique का उपयोग करना चुन सकते हैं, क्योंकि यह वास्तव में वह कलाकार है जिसे आप ढूंढ रहे हैं, लेकिन क्या वह वास्तव में आपको कुछ भी लाभ पहुंचाता है। इसका मुख्य उद्देश्य यह दस्तावेज करना है कि आप कलाकारों द्वारा किए जा रहे मूल्य को immutable के रूप में माना जा सकता है और इसमें कोई अन्य संदर्भ नहीं है। अपने उदाहरण को देखते हुए, यह अनिवार्य रूप से सच है, क्योंकि यह फ़ंक्शन में आखिरी चीज है, लेकिन चाहे आप इसे सामान्य रूप से करना चाहते हैं, आप पर निर्भर है।यह देखते हुए कि यह एक स्थैतिक सरणी है जो आपके द्वारा खराब होने पर स्मृति समस्याओं का जोखिम उठाती है और आप इसे किसी फ़ंक्शन पर पास करते हैं जो इसे संदर्भित करने के संदर्भ में अनुमति देता है, मुझे यकीन नहीं है कि assumeUnique सबसे अच्छा विकल्प है। लेकिन फिर, यह आप पर निर्भर है।

भले ही, यदि आप एक कलाकार कर रहे हैं (चाहे वह स्पष्ट रूप से हो या assumeUnique के साथ), तो आपको यह सुनिश्चित करने की आवश्यकता है कि जिस कार्य को आप पास कर रहे हैं वह उस डेटा के संदर्भ को रिसाव नहीं करेगा जो आप हैं इसे पास करना यदि ऐसा होता है, तो आप परेशानी के लिए पूछ रहे हैं।

अन्य समाधान, निश्चित रूप से, फ़ंक्शन को बदलना है ताकि इसे const(char)[] लगे, लेकिन यह अभी भी आपके द्वारा गुज़रने वाले डेटा के संदर्भों को लीक करने का जोखिम चलाता है। इसलिए, आपको अभी भी निश्चित होना चाहिए वास्तव में क्या कार्य करने जा रहा है। यदि यह pure है, तो const(char)[] (या कुछ भी जो const(char)[] हो सकता है) वापस नहीं लौटाता है, और कोई भी तरीका नहीं है कि यह किसी भी फ़ंक्शन के अन्य तर्कों के माध्यम से रिसाव कर सकता है, तो आप सुरक्षित हैं, लेकिन यदि उनमें से कोई भी सत्य नहीं है , तो आपको सावधान रहना होगा। तो, आखिरकार, मेरा मानना ​​है कि string पर कास्टिंग करने के बजाय const(char)[] का उपयोग करने वाले सभी वास्तव में आपको खरीदते हैं कि आपको नहीं डालना है। यह अभी भी बेहतर है, क्योंकि यह कास्ट को खराब करने के जोखिम से बचाता है (और जब आप कर सकते हैं तो कास्टिंग से बचने के लिए सामान्य रूप से बेहतर होता है), लेकिन आपके पास अभी भी वही चीजें हैं जो संदर्भों से बचने के संबंध में चिंता करने के लिए हैं।

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

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

+0

रेंडरटेक्स्ट बनाने के बारे में कैसे एक "स्कोप कॉन्स (char) []" लेते हैं? "स्कोप स्टोरेज क्लास का अर्थ है कि पैरामीटर में संदर्भ बच नहीं सकते हैं (उदा। ग्लोबल वैरिएबल को असाइन किया गया है)।" – jpf

+0

@jpf: क्या आप इसके बारे में निश्चित हैं? डीएमडी इसे अनुमति देता है। –

+0

यह डी 2 भाषा संदर्भ से उद्धरण था: http://www.digitalmars.com/d/2.0/function.html अनुभाग "फ़ंक्शन पैरामीटर्स"। हालांकि मुझे टीडीपीएल में कुछ ऐसा नहीं मिल रहा है। लेकिन अगर मैं अभी तक ठीक से लागू नहीं हुआ हूं तो मुझे आश्चर्य नहीं होगा ;-) – jpf

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

  • कोई संबंधित समस्या नहीं^_^