2008-12-12 23 views
36

बिना मैं एक स्थिति है जहाँ मैं इस तरह के रूप डेटा की बड़ी (कई जीबी की) मात्रा में संसाधित करने की जरूरत है:आरंभ std :: चार * से स्ट्रिंग प्रतिलिपि

  1. कई छोटे (सी चार जोड़कर एक बड़ी स्ट्रिंग का निर्माण *) तार
  2. स्ट्रिंग
  3. एक सी ++ प्रसंस्करण के लिए स्थिरांक std :: स्ट्रिंग में स्ट्रिंग परिवर्तित ट्रिम (रीड ओनली)
  4. दोहराने

दा प्रत्येक पुनरावृत्ति में टा स्वतंत्र हैं।

मेरा सवाल यह है कि, मैं इस समय आवंटित स्मृति उपयोग को कम करने (यदि संभव हो तो समाप्त करना) छोटा करना चाहता हूं, क्योंकि फिलहाल यह मेरी सबसे बड़ी प्रदर्शन समस्या है।

क्या सी स्ट्रिंग (char *) को एक stl C++ स्ट्रिंग (std :: string) में परिवर्तित करने का कोई तरीका है बिना std :: स्ट्रिंग को आंतरिक रूप से आवंटित/डेटा कॉपी करने के लिए?

वैकल्पिक रूप से, क्या मैं स्ट्रिंगस्ट्रीम या किसी बड़े बफर का पुन: उपयोग करने के समान कुछ उपयोग कर सकता हूं?

संपादित करें: जवाब के लिए धन्यवाद, स्पष्टता के लिए, मुझे लगता है कि एक संशोधित सवाल होगा:

मैं कुशलता से कैसे बना सकते हैं (कई संलग्न कर देता है के माध्यम से) एक STL सी ++ स्ट्रिंग। और यदि एक लूप में यह क्रिया निष्पादित कर रही है, जहां प्रत्येक पाश पूरी तरह से स्वतंत्र है, तो मैं इस आवंटित स्थान का पुन: उपयोग कैसे कर सकता हूं।

उत्तर

17

क्या चरण 1 में सी ++ स्ट्रिंग का उपयोग करना संभव है? यदि आप string::reserve(size_t) का उपयोग करते हैं, तो आप छोटे स्ट्रिंग को जोड़ते समय एकाधिक ढेर आवंटन को रोकने के लिए एक बड़ा पर्याप्त बफर आवंटित कर सकते हैं, और फिर आप शेष शेष चरणों में उसी सी ++ स्ट्रिंग का उपयोग कर सकते हैं।

this linkreserve फ़ंक्शन पर अधिक जानकारी के लिए देखें।

+0

आपका समाधान लगता है कि मैं क्या करता हूं, हालांकि, जब आप कहते हैं कि "आप केवल उसी सी ++ स्ट्रिंग का उपयोग कर सकते हैं" क्या आपका मतलब स्पष्ट() का उपयोग करना है, और फिर अगली स्ट्रिंग बनाना जारी रखना है? – Akusete

+0

यह समाधान मेरे लिए अपनाने के लिए सबसे आसान है, वर्तमान में, हालांकि मुझे यकीन नहीं है कि पुन: उपयोग वास्तव में मानक द्वारा निर्दिष्ट किया गया है (हालांकि यह मेरे कार्यान्वयन पर काम करता प्रतीत होता है) – Akusete

+0

स्पष्ट() का उपयोग करना चाहिए।जहां तक ​​मुझे पता है, स्पष्ट() स्ट्रिंग द्वारा उपयोग की गई स्मृति को मुक्त नहीं करता है, और इसलिए आरक्षित() द्वारा आवंटित स्थान को प्रभावित नहीं करता है। –

1

क्या प्रत्येक पुनरावृत्ति पर्याप्त स्वतंत्र है कि आप प्रत्येक पुनरावृत्ति के लिए एक ही std :: स्ट्रिंग का उपयोग कर सकते हैं? कोई उम्मीद करेगा कि आपका std :: स्ट्रिंग कार्यान्वयन स्मृति का पुन: उपयोग करने के लिए पर्याप्त स्मार्ट है यदि आप किसी अन्य के लिए पहले इस्तेमाल किए जाने पर इसे एक कॉन्स char * असाइन करते हैं।

एक char * को std :: स्ट्रिंग में असाइन करना हमेशा कम से कम डेटा की प्रतिलिपि बनाना चाहिए। स्मृति प्रबंधन std :: स्ट्रिंग का उपयोग करने के मुख्य कारणों में से एक है, इसलिए आप इसे ओवरराइड करने में सक्षम नहीं होंगे।

7

वास्तव में बड़े तारों में सहायता के लिए एसजीआई के वर्ग एसटीएल में रस्सी है।
गैर मानक लेकिन उपयोगी हो सकता है।

http://www.sgi.com/tech/stl/Rope.html

जाहिर रस्सी मानक :-)
नोट डेवलपर मजाक के अगले संस्करण में है। एक रस्सी एक बड़ी स्ट्रिंग है। (हा हा) :-)

18

आप वास्तव में डेटा कॉपी किए बिना std :: स्ट्रिंग नहीं बना सकते हैं। एक स्ट्रिंगस्ट्रीम शायद स्मृति को पास से पास करने का पुन: उपयोग करेगा (हालांकि मुझे लगता है कि यह मानक वास्तव में चुप है या नहीं), लेकिन यह अभी भी प्रतिलिपि से बच नहीं पाएगा।

इस प्रकार की समस्या का एक आम दृष्टिकोण कोड लिखना है जो चरण 3 में डेटा को प्रारंभ/अंत इटरेटर जोड़ी का उपयोग करने के लिए संसाधित करता है; तो यह आसानी से एक std :: स्ट्रिंग, वर्णों का एक वेक्टर, कच्चे पॉइंटर्स की एक जोड़ी आदि को संसाधित कर सकता है। इसे एक कंटेनर प्रकार जैसे std :: स्ट्रिंग को पास करने के विपरीत, यह अब पता नहीं होगा या स्मृति को आवंटित करने की परवाह नहीं करेगा, चूंकि यह अभी भी कॉलर से संबंधित होगा। इस विचार को अपने तार्किक निष्कर्ष पर ले जाना boost::range है, जो सभी अधिभारित कन्स्ट्रक्टर को अभी भी कॉलर को एक स्ट्रिंग/वेक्टर/सूची/किसी भी प्रकार के कंटेनर को .begin() और .end(), या अलग इटरेटर्स के साथ पास करने देता है।

अपने प्रसंस्करण कोड को मनमाने ढंग से इटरेटर श्रेणी पर काम करने के लिए लिखा है, तो आप एक कस्टम इटरेटर भी लिख सकते हैं (जितना कठिन लगता है, मूल रूप से केवल कुछ मानक टाइपिफ़ीफ के साथ एक ऑब्जेक्ट नहीं है, और ऑपरेटर ++/*/=/== /! = आगे-केवल इटेटरेटर प्राप्त करने के लिए अधिभारित) जो अगली टुकड़े को आगे बढ़ने का ख्याल रखता है, जब भी वह काम कर रहा है, जिस पर यह काम कर रहा है, व्हाइटस्पेस पर छोड़ रहा है (मुझे लगता है कि आप ट्रिम द्वारा क्या मतलब है) । कि आपको पूरी स्ट्रिंग को पूरी तरह से इकट्ठा नहीं करना पड़ेगा। चाहे यह जीत होगी या नहीं, इस पर निर्भर करता है कि कितने टुकड़े/आपके पास कितने टुकड़े हैं। यह अनिवार्य रूप से मार्टिन यॉर्क द्वारा वर्णित एसजीआई रस्सी है: एक स्ट्रिंग जहां एक संगत बफर की बजाय टुकड़ों की एक लिंक की गई सूची बनाती है, जो इस प्रकार अधिक लंबे मूल्यों के लिए उपयुक्त है।


अद्यतन (के बाद से मैं अभी भी इस जवाब पर कभी upvotes देखें):

सी ++ 17 एक और विकल्प प्रस्तुत करता है:, std::string_view है, जो कई समारोह हस्ताक्षर में std :: स्ट्रिंग की जगह एक गैर है एक चरित्र डेटा के संदर्भ में संदर्भ। यह std :: स्ट्रिंग से पूरी तरह से परिवर्तनीय है, लेकिन अनावश्यक प्रतिलिपि std :: स्ट्रिंग लगाए जाने से बचने के लिए, कहीं और स्वामित्व वाले संगत डेटा से स्पष्ट रूप से बनाया जा सकता है।

+0

मुझे लगता है कि आपका समाधान सबसे अच्छा तरीका है (प्रसंस्करण कोड काटना) दुर्भाग्य से इस स्थिति में यह एक विकल्प नहीं है। – Akusete

+1

क्या बफर पुन: उपयोग करने के लिए मानक मानक तरीका है? मैं सिर्फ एक विशिष्ट मंच पर कार्यान्वयन पर भरोसा नहीं करना चाहता हूं। – Akusete

+0

जब तक कि प्रसंस्करण कोड एक लाइब्रेरी फ़ंक्शन नहीं है जो इटेटर और न ही तारों का उपयोग नहीं करता है, केवल एक सादा पुराना 'char * '+ आकार। – SasQ

0

इस मामले में, यह एक std :: स्ट्रिंग को असाइन करने के बजाय, char * को सीधे संसाधित करना बेहतर हो सकता है।

+3

हां यह होगा, हालांकि इनपुट (सी char * ') और आउटपुट (std :: string) मेरे नियंत्रण में नहीं हैं। – Akusete

4

यह एक पार्श्व सोच जवाब है, सीधे सवाल को संबोधित नहीं करते बल्कि इसके आसपास "सोच"। उपयोगी हो सकता है, शायद नहीं ...

std :: स्ट्रिंग की रीडोनली प्रोसेसिंग को वास्तव में std :: स्ट्रिंग की विशेषताओं के बहुत ही जटिल सबसेट की आवश्यकता नहीं है। क्या कोई संभावना है कि आप कोड पर खोज/प्रतिस्थापन कर सकते हैं जो std :: तारों पर सभी प्रसंस्करण करता है, इसलिए इसके बजाय कुछ और प्रकार लगता है? रिक्त कक्षा से शुरू करें:

कक्षा lightweight_string {};

फिर lightd_string के साथ सभी std :: स्ट्रिंग संदर्भों को प्रतिस्थापित करें। एक ड्रॉप-इन प्रतिस्थापन के रूप में कार्य करने के लिए lightweight_string पर वास्तव में किस ऑपरेशन की आवश्यकता है, यह जानने के लिए एक संकलन करें। फिर आप अपना कार्यान्वयन कार्य कर सकते हैं हालांकि आप चाहते हैं।

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