2010-01-31 9 views
12

StringPiece class in Chromium's source code के प्रलेखन से:क्या कोई कारण हैं कि स्ट्रिंगपीस/स्ट्रिंगरफ मुहावरे अधिक लोकप्रिय नहीं है?

// A string-like object that points to a sized piece of memory. 
// 
// Functions or methods may use const StringPiece& parameters to accept either 
// a "const char*" or a "string" value that will be implicitly converted to 
// a StringPiece. 
// 
// Systematic usage of StringPiece is encouraged as it will reduce unnecessary 
// conversions from "const char*" to "string" and back again. 

उपयोग का उदाहरण:

void foo(StringPiece const & str) // Pass by ref. is probably not needed 
{ 
    // str has same interface of const std::string 
} 

int main() 
{ 
    string bar("bar"); 
    foo(bar); // OK, no mem. alloc. 

    // No mem. alloc. either, would be if arg. of "foo" was std::string 
    foo("baz"); 
} 

इस तरह के एक महत्वपूर्ण और स्पष्ट अनुकूलन की तरह लगता है मैं नहीं समझ सकता है कि क्यों यह और अधिक व्यापक नहीं है, और क्यों स्ट्रिंगपीस के समान एक वर्ग पहले से ही मानक में नहीं है।

क्या इस कारण से मुझे अपने कोड में string और char* पैरामीटर के उपयोग को प्रतिस्थापित नहीं करना चाहिए? क्या सी ++ मानक पुस्तकालयों में पहले से ही ऐसा कुछ है?

अद्यतन। मैंने सीखा है कि एलएलवीएम का स्रोत इसी तरह की अवधारणा का उपयोग करता है: StringRef कक्षा।

+0

मुझे इसे सैद्धांतिक विचार के रूप में पसंद है। मुझे आश्चर्य है कि यह "प्रशिक्षण" के बिना अभ्यास में कितना भ्रमित होगा। – jmucchiello

+1

पुरानी पोस्ट, लेकिन भविष्य के पाठकों के लिए यह ध्यान रखना चाहिए कि यह प्रस्तावित किया गया है: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html –

उत्तर

-7

क्योंकि परेशान क्यों? कॉपी elision और/या संदर्भ द्वारा पास के साथ, std::string के लिए स्मृति आवंटन आमतौर पर भी बचा जा सकता है।

सी ++ में स्ट्रिंग स्थिति अभी भी अधिक स्ट्रिंग कक्षाओं को जोड़ने के बिना पर्याप्त भ्रमित है।

अगर भाषा को स्क्रैच से फिर से डिजाइन किया जाना था, या यदि पीछे की संगतता कोई समस्या नहीं थी, तो यह सी ++ में हैंडलिंग करने के लिए कई संभावित सुधारों में से एक है। लेकिन अब हम char* और std::string दोनों के साथ फंस गए हैं, मिश्रण में एक स्ट्रिंग-स्टाइल क्लास जोड़ने से सीमित लाभ के साथ बहुत भ्रम पैदा होगा।

इसके अलावा, इटेटरेटरों की एक जोड़ी के साथ समान रूप से अधिक idiomatically हासिल नहीं किया गया है? यदि मैं वर्णों का अनुक्रम पास करना चाहता हूं, चाहे वे स्ट्रिंग या char* से संबंधित हों, तो मुझे इन्हें सीमित करने के लिए केवल एक जोड़ी का उपयोग क्यों नहीं करना चाहिए?

+3

लेकिन अगर आप "दो iterators" तरीका अपनाते हैं, तो आप एक वर्ग StringPiece के अनुरूप है कि आप एक सुविधाजनक स्ट्रिंग की तरह इंटरफ़ेस देता है आविष्कार करने के लिए किया है। और आपके कार्यों की पहली पंक्ति हमेशा "स्ट्रिंगरेंज स्ट्र (str_beg, str_end)" जैसी कुछ होगी; "।अब तक का सबसे अच्छा मूल्यांकन प्रदान करने के लिए वैसे भी स्वीकृत। – Manuel

+0

सुविधाजनक स्ट्रिंग-जैसे इंटरफ़ेस के बारे में सही है, लेकिन फिर, याद रखें कि इटरेटर पहले से ही C++ में बेवकूफ हैं। मुझे नहीं लगता कि आपके कार्यों को इटरेटर से स्ट्रिंगेंज बनाने की आवश्यकता क्यों होगी। इसके बजाए, पूरे स्ट्रिंग मैनिपुलेशन इंटरफेस को शुरू करने के लिए इटेटर पर मुफ्त कार्यों के रूप में प्रदान किया जाना चाहिए था। बूस्ट की स्ट्रिंगअल्गो लाइब्रेरी इसमें से अधिकांश को हल करती है। – jalf

+0

मुझे नहीं लगता कि आप वास्तव में पसंद करेंगे जो आप सुझा रहे हैं। इटरेटर के संदर्भ में 'strA + strb + strC' के रूप में सरल कुछ कल्पना कीजिए। – Manuel

0

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

यह भी ध्यान दें कि एक अच्छा गठित कार्यक्रम या तो स्ट्रिंग या कॉन्स चार * का उपयोग करना चाहिए;)।

+0

@ कॉर्नेल किसिलेविक: लेकिन कैसे है यह बेकार है अगर यह स्मृति आवंटन बचाता है, जो स्ट्रिंग लंबा होने पर महंगा हो सकता है? मैंने सोचा कि सी ++ "आप जो भी उपयोग नहीं करते हैं उसके लिए भुगतान न करें" के बारे में था। – Manuel

+0

@ मैनुअल - यह डीआरवाई सिद्धांत का उल्लंघन करता है, और उस –

+3

से आने वाले सभी पतन क्या यह DRY से संबंधित है? – Manuel

2

StringPiece स्ट्रिंग डेटा है कि इसके निर्माता को पारित कर दिया है करने के लिए एक सूचक रहता है। इस प्रकार यह स्ट्रिंगपीस से अधिक होने के लिए उस स्ट्रिंग के जीवनकाल पर निर्भर करता है। यह गारंटी दी जाती है कि आप स्ट्रिंगपीस को फ़ंक्शन पैरामीटर के रूप में उपयोग कर रहे हैं; ऐसा नहीं है यदि आप उदाहरण के लिए कक्षा सदस्य में स्ट्रिंग की एक प्रति रखते हैं।

यह std :: स्ट्रिंग के रूप में सार्वभौमिक नहीं है, और यह निश्चित रूप से इसके लिए एक प्रतिस्थापन नहीं है।

+0

हां, आपको इसकी एक प्रति कभी नहीं रखना चाहिए। मुझे लगता है कि इसकी प्रतिलिपि ctor बनाकर इसे छोटा रूप से लागू किया जा सकता है। और सेशन = निजी। Std :: स्ट्रिंग के लिए सार्वभौमिक प्रतिस्थापन नहीं होने के नाते, मैं सहमत हूं। दोनों एक साथ काम करने के इरादे से हैं। std :: string => सामान्य उपयोग; StringPiece => केवल केवल पढ़ने के लिए समारोह पैरामीटर – Manuel

+0

के रूप में मैं काम की अनुमति नहीं देने की वजह से ही मैं की आवश्यकता होगी कि वर्ग पर सभी तरीकों स्थिरांक घोषित किया जाना, मजबूत है कि यह एक स्थिरांक वस्तु है जाएगा। मुझे लगता है कि कॉपी सीटीआर घोषित करने और जोड़ों में असाइनमेंट का अभ्यास एकमात्र कारण है जो प्रतिलिपि ctor को अनुमति नहीं देता है। – jmucchiello

+0

@jmucchiello - और भी स्ट्रिंग की अपनी कॉपी को भंडारण और यह जीवित नहीं रह रखते हुए समारोह है कि से लोगों को रोकने के लिए। मुझे नहीं लगता कि आप तब तक इसे रोक सकते हैं जब तक आप प्रतिलिपि ctor को अक्षम नहीं करते। – Manuel

4

प्रश्न का पहले से ही बहुत अच्छा जवाब दिया गया है, लेकिन कुछ और संदर्भ देने के लिए, StringPiece पैटर्न Google पर आंतरिक रूप से व्यापक रूप से उपयोग किया जाता है और यह कई सालों से रहा है। Google कोडिंग दिशानिर्देशों में इसकी दृढ़ता से अनुशंसा की जाती है, जो लगभग निश्चित रूप से क्रोम (और बाद में क्रोमियम) ने इसे अपनाया है।

0

स्ट्रिंगपीस बहुत अच्छा है लेकिन टुकड़े को समाप्त नहीं किया गया है। यदि आपको निचले स्तर के इंटरफेस को पास करने की आवश्यकता है जो नल टर्मिनेटेड स्ट्रिंग्स लेते हैं, तो आपको स्ट्रिंगपीस को एक नल टर्मिनेटेड स्ट्रिंग में कॉपी करने की आवश्यकता होती है।

(सभी ने एसटीएल या std :: स्ट्रिंग में खरीदा नहीं है।)

8

बिट बाद में, लेकिन ... StringPiece पीछे

आइडिया बहुत अच्छा है। कक्षा std::string और const char * दोनों को कैप्चर कर सकती है और उन्हें एक फ़ंक्शन में पास कर सकती है।

void process(const StringRef s){ 
    // do something 
} 

process("Hello"); // const char * 
std::string s = "Hello"; 
process(s); // std::string 
process(std::string("Hello")); // std::string rvalue 

तो समारोह std::string स्वीकार किए जाते हैं आप वास्तव में एक अस्थायी वस्तु बनाने यदि आप const char * गुजरती हैं और पूरे चार (memcpy साथ उदाहरण के लिए) की नकल की है: यहाँ एक उदाहरण है।

आपको लाइफटाइम के बारे में चिंता करने की भी आवश्यकता नहीं है, क्योंकि आप StringRef को फ़ंक्शन/विधि में पास कर रहे हैं।

रहे हैं इस तरह के वर्ग में:

  • गूगल - StringPiece

  • बढ़ावा - बढ़ावा :: string_ref

  • LLVM - StringRef

मेरा अपना (अधूरा) कार्यान्वयन यहां देखा जा सकता है:
https://github.com/nmmmnu/HM3/blob/master/include/stringref.h

अद्यतन 2016:

सी ++ 17 में, वहाँ std::string_view हैं। मैंने विवरण में इसका अध्ययन नहीं किया, लेकिन आम तौर पर यह एक ही विचार है। मेरे कार्यान्वयन के समान ही constexpr सी-टोर है, इसलिए आप संकलन समय पर ऑब्जेक्ट बना सकते हैं और अन्य constexpr फ़ंक्शंस के साथ इसका उपयोग कर सकते हैं।

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