2015-09-23 14 views
19

std::string के लिए कई constructors हैं। मैं पुनर्वितरण से बचने के लिए एक रास्ता तलाश रहा था और मुझे हैरान है कि एक भरने वाला कन्स्ट्रक्टर है लेकिन कोई "रिजर्व" कन्स्ट्रक्टर नहीं है।std :: string के लिए कोई रिजर्व कन्स्ट्रक्टर क्यों नहीं है?

std::string (size_t n, char c); 

लेकिन कोई

std::string (size_t n); 

तो मैं reserve() कॉल करनी होगी के बाद यह पहले से ही डिफ़ॉल्ट (मेरे मामले में 16 बाइट्स), बस तुरंत पुनः आवंटित करने के लिए आवंटित करते हैं?

क्या ऐसा कोई कारण है कि ऑब्जेक्ट बनने के बजाय सीधे स्थान आरक्षित करने के लिए ऐसा कोई कन्स्ट्रक्टर नहीं है, इसे मैन्युअल रूप से करने के बजाय? या क्या मुझे कुछ याद आ रहा है और ऐसा करने का कोई तरीका है?

भरने निर्माता का उपयोग करना, क्योंकि यह स्मृति के माध्यम से लूप सिर्फ ओवरराइट प्राप्त करने के लिए होगा, और यह भी एक गलत आकार का कारण है, क्योंकि s.length() रिपोर्ट N बजाय 0 समय की बर्बादी है।

+0

क्या आप वाकई 16 बाइट प्रति डिफ़ॉल्ट आरक्षित हैं? ('sizeof (std :: string) 'के साथ इसके साथ कुछ लेना देना नहीं है) – deviantfan

+3

@deviantfan, यह कार्यान्वयन-परिभाषित – SingerOfTheFall

+0

@ सिंगरऑफ दफॉल हां, 16 बाइट की तरह भी है। मैं विशेष रूप से डेवोलस कार्यान्वयन – deviantfan

उत्तर

3

यह सब अनुमान है, लेकिन मैं कोशिश करूंगा।

यदि आप पहले से ही आवश्यक स्ट्रिंग के आकार को जानते हैं, तो आप शायद कहीं और डेटा से कॉपी कर रहे होंगे, उदा। एक और स्ट्रिंग से। उस स्थिति में, आप उन रचनाकारों में से एक को कॉल कर सकते हैं जो तुरंत डेटा कॉपी करने के लिए char * या const std::string & स्वीकार करते हैं।

इसके अलावा, मैं नहीं देख सकता कि स्ट्रिंग बनाने के ठीक बाद reserve का उपयोग क्यों करना एक बुरी बात है। हालांकि यह कार्यान्वयन परिभाषित किया गया है, मुझे लगता है कि यह इस कोड के लिए कोई मतलब होगा ग्रहण करेंगे:,

std::string str; 
str.reserve(100); 

100 तत्वों, नहीं 116 के कुल के लिए स्मृति को आबंटित करने ("पहले 16 आवंटित में के रूप में फिर उन्हें मुक्त और आवंटित 100 से अधिक आवंटित "), इस प्रकार गैर-मौजूदा रिजर्व कन्स्ट्रक्टर पर कोई प्रदर्शन प्रभाव नहीं पड़ता है।

इसके अलावा, अगर आप बस डिफ़ॉल्ट आवंटन के बिना एक खाली स्ट्रिंग बिल्कुल चाहते हैं, आप शायद std::string str(0, ' '); जो अमान्य कर उपयोग कर सकते हैं बिंदु "भरने निर्माता का उपयोग करते हुए समय की बर्बादी है"।

+0

वह 'std :: string str (0, ''); 'वास्तव में डिफ़ॉल्ट आवंटन (VS2010) को रोक दिया। मैंने कथित तौर पर यह एक डीबग बिल्ड में होता है, इसलिए यह अब कोई समस्या नहीं होगी, लेकिन वैसे भी, यह वही था जो मैं ढूंढ रहा था। – Devolus

+0

जब 'std :: string' आपको डिफ़ॉल्ट कन्स्ट्रक्टर से कुछ प्रारंभिक क्षमता प्रदान करता है, ऐसा इसलिए होता है क्योंकि वे कुछ स्टैक स्पेस के साथ अंतर्निहित आते हैं। आवंटित करने और रद्द करने के लिए कुछ खास नहीं है। –

0

आप मूल रूप से प्रत्येक std::string विधि के बारे में एक ही प्रश्न पूछ सकते हैं जो एक निर्माता के रूप में नहीं है।

उदाहरण के लिए, हमारे पास एक कन्स्ट्रक्टर क्यों नहीं है जो एकाधिक तारों को लेता है और उन्हें नव निर्मित स्ट्रिंग में एक-एक करके जोड़ता है?

ऐसे कई कारण हो सकते हैं जो एक रचनाकार को अधिभारित न करें जो स्मृति को आरक्षित करता है। मुझे लगता है कि ऑब्जेक्ट ओरिएंटेड सेटमाइंड में, "आरक्षित मेमोरी स्ट्रिंग" का विचार थोड़ा अजीब है। स्ट्रिंग वर्णों के अनुक्रम का प्रतिनिधित्व करती है, न कि इसके पीछे की स्मृति - जो कार्यान्वयन विवरण है, मुख्य सुविधा नहीं।
जब कोई नया पुनर्विक्रय खोलता है, तो क्या वह खुद को सोचता है "जब यह बहादुर आखिरकार खुला रहता है, तो खुलने के बहुत ही पल में मैं 100 लोगों के समूह के लिए 100 बैठकों को आरक्षित कर सकता हूं जो शायद या नहीं आ सकते हैं!"

लेकिन आपका प्रश्न स्पष्ट रूप से कुछ छोड़ देता है: सी ++ में उचित बफर ऑब्जेक्ट्स की कमी। आप रिजर्व कन्स्ट्रक्टर के बारे में पूछते हैं क्योंकि आप स्ट्रिंग का उपयोग बफर के रूप में करना चाहते हैं, लेकिन उन्हें शून्य-प्रारंभ करना बहुत महंगा है।स्मृति को आरक्षित करने से आपको स्ट्रिंग आकार से परे लिखने नहीं दिया जाएगा।
इसलिए इस समस्या का समाधान unique_ptr<char[]> का उपयोग करना है जो शून्य नहीं होगा - वर्णों को आरंभ करें, फिर भी आपको वह RAII शैली देगा जो आप खोज रहे हैं।

+0

मुझे नहीं लगता कि कैसे एक unique_ptr ऑब्जेक्ट यहां मदद करेगा क्योंकि यह मुझे std :: स्ट्रिंग की कार्यक्षमता नहीं देता है। – Devolus

+0

उदाहरण के लिए क्या कार्यक्षमता? –

+0

उदाहरण के लिए: str + = txt; – Devolus

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