C++ 11 में गाय std:: स्ट्रिंग कार्यान्वयन की वैधता




c++11 stdstring (4)

क्या COW+ 11 और बाद में गाय basic_string प्रतिबंधित है?

के बारे में

" क्या मैं सही हूं कि सी ++ 11 std::string गाय आधारित कार्यान्वयन स्वीकार नहीं करता है?

हाँ।

के बारे में

" यदि हां, तो क्या यह प्रतिबंध स्पष्ट रूप से नए मानक (कहां) में कहीं कहा गया है?

लगभग सीधे, कई परिचालनों के लिए निरंतर जटिलता की आवश्यकताओं के कारण, जो गाय क्रियान्वयन में स्ट्रिंग डेटा की ओ ( एन ) भौतिक प्रतिलिपि की आवश्यकता होगी।

उदाहरण के लिए, सदस्य कार्यों के लिए

auto operator[](size_type pos) const -> const_reference;
auto operator[](size_type pos) -> reference;

... जो एक गाय कार्यान्वयन में स्ट्रिंग मान को अन-साझा करने के लिए स्ट्रिंग डेटा कॉपी करने के लिए ट्रिगर करेगा, सी ++ 11 मानक आवश्यक है

सी ++ 11 §21.4.5 / 4 :

" जटिलता: निरंतर समय।

... जो इस तरह की डेटा प्रतिलिपि का नियम बनाता है, और इसलिए, गाय।

सी ++ 03 ने इन निरंतर जटिलता आवश्यकताओं को नहीं, और कुछ प्रतिबंधित प्रतिबंधों के तहत rbegin() , operator[]() को कॉल करने की इजाजत देता है operator[]() , at() , begin() , rbegin() , end() , या rend() संदर्भों को इंगित करने के लिए, पॉइंटर्स और इटरेटर स्ट्रिंग आइटम का जिक्र करते हैं, यानी संभवतः गाय डेटा प्रतिलिपि बनाना संभव है। यह समर्थन सी ++ 11 में हटा दिया गया था।

क्या गाय को सी ++ 11 अमान्यता नियमों के माध्यम से भी प्रतिबंधित किया गया है?

एक और जवाब में जो लेखन के समय समाधान के रूप में चुना जाता है, और जो भारी रूप से उखाड़ फेंक दिया जाता है और इसलिए जाहिर है, यह कहा जाता है कि

" एक गाय स्ट्रिंग के लिए, गैर- const operator[] कॉल करने के लिए operator[] को प्रतिलिपि बनाने और संदर्भों को अमान्य करने की आवश्यकता होगी, जिसे [उद्धृत] अनुच्छेद [सी ++ 11 §21.4.1 / 6] द्वारा अस्वीकृत किया गया है। इसलिए, सी ++ 11 में गाय स्ट्रिंग होने के लिए अब कानूनी नहीं है।

यह दावा दो मुख्य तरीकों से गलत और भ्रामक है:

  • यह गलत तरीके से इंगित करता है कि केवल गैर- const आइटम const को गाय डेटा कॉपी करने की आवश्यकता होती है।
    लेकिन const आइटम const को डेटा प्रतिलिपि को ट्रिगर करने की आवश्यकता होती है, क्योंकि वे क्लाइंट कोड को संदर्भ या पॉइंटर्स बनाने की अनुमति देते हैं (सी ++ 11 में) इसे बाद में उन अभियानों के माध्यम से अमान्य करने की अनुमति नहीं है जो गाय डेटा प्रतिलिपि को ट्रिगर कर सकते हैं।
  • यह गलत तरीके से मानता है कि गाय डेटा प्रतिलिपि संदर्भ अमान्यता का कारण बन सकती है।
    लेकिन एक सही कार्यान्वयन में गाय डेटा प्रतिलिपि, स्ट्रिंग मान को अन-साझा करना, किसी भी संदर्भ में अमान्य होने से पहले एक बिंदु पर किया जाता है।

यह देखने के लिए कि basic_string का सही C ++ 11 गाय कार्यान्वयन कैसे काम करेगा, जब ओ (1) आवश्यकताएं जो इसे अमान्य बनाती हैं, उन्हें एक कार्यान्वयन के बारे में सोचें जहां एक स्ट्रिंग स्वामित्व नीतियों के बीच स्विच हो सकती है। पॉलिसी के साथ एक स्ट्रिंग इंस्टेंस शुरू होता है। इस नीति के साथ सक्रिय कोई बाहरी आइटम संदर्भ नहीं हो सकता है। उदाहरण अनन्य नीति में संक्रमण कर सकता है, और ऐसा तब करना चाहिए जब किसी आइटम संदर्भ को संभावित रूप से बनाया गया हो जैसे कि .c_str() (कम से कम अगर वह आंतरिक बफर को पॉइंटर उत्पन्न करता है)। मूल्य के स्वामित्व को साझा करने वाले कई उदाहरणों के सामान्य मामले में, इसमें स्ट्रिंग डेटा की प्रतिलिपि होती है। अनन्य नीति में उस संक्रमण के बाद इंस्टेंस केवल एक ऑपरेशन द्वारा Sharable पर वापस जा सकता है जो असाइनमेंट जैसे सभी संदर्भों को अमान्य करता है।

इसलिए, उस उत्तर के निष्कर्ष के दौरान, गाय तारों को अस्वीकार कर दिया गया है, सही है, प्रस्तावित तर्क गलत और दृढ़ता से भ्रामक है।

मुझे संदेह है कि इस गलतफहमी का कारण सी ++ 11 के अनुबंध में एक गैर-मानक नोट है:

सी ++ 11 §C.2.11 [diff.cpp03.strings], लगभग §21.3:

बदलें : basic_string आवश्यकताओं को अब संदर्भ-गिनती तारों की अनुमति नहीं है
तर्क: संदर्भ-गणना वाले तारों के साथ अमान्यता अलग-अलग है। यह परिवर्तन इस अंतर्राष्ट्रीय मानक के लिए व्यवहार (एसआईसी) को नियमित करता है।
मूल सुविधा पर प्रभाव: मान्य सी ++ 2003 कोड इस अंतर्राष्ट्रीय मानक में अलग-अलग निष्पादित हो सकता है

यहां तर्क प्राथमिकता बताता है कि क्यों ने सी ++ 03 विशेष गाय समर्थन को हटाने का फैसला किया। यह तर्क, क्यों , मानक प्रभावी रूप से गाय कार्यान्वयन को अस्वीकार नहीं करता है। मानक ओ (1) आवश्यकताओं के माध्यम से गाय को अस्वीकार करता है।

संक्षेप में, सी ++ 11 अमान्यता नियम std::basic_string गाय कार्यान्वयन को रद्द नहीं करते हैं। लेकिन वे कम से कम एक जी ++ के मानक लाइब्रेरी कार्यान्वयन में से एक की तरह एक उचित कुशल अप्रतिबंधित सी ++ 03-शैली गाय कार्यान्वयन को रद्द करते हैं। विशेष सी ++ 03 गाय समर्थन ने const के लिए सूक्ष्म, जटिल नियमों की लागत पर विशेष रूप से const आइटम const का उपयोग करके व्यावहारिक दक्षता की अनुमति दी:

सी ++ 03 §21.3 / 5 जिसमें "पहला कॉल" गाय समर्थन शामिल है:

" basic_string अनुक्रम के तत्वों का जिक्र करने वाले संदर्भ, पॉइंटर्स और इटरेटर उस basic_string ऑब्जेक्ट के निम्न उपयोगों से अमान्य हो सकते हैं:
- गैर-सदस्य फ़ंक्शन swap() (21.3.7.8), operator>>() (21.3.7.9), और getline() (21.3.7.9) के लिए एक तर्क के रूप में।
- basic_string::swap() लिए एक तर्क के रूप में।
- कॉलिंग data() और c_str() सदस्य फ़ंक्शंस।
- operator[]() , at() , begin() , rbegin() , end() , और rend() को छोड़कर, गैर- const सदस्य फ़ंक्शंस को कॉल begin()
- उपर्युक्त उपयोगों में से किसी भी के बाद insert() के रूपों को छोड़कर और erase() जो इसे पुनरावर्तक लौटाता है, गैर- const सदस्य फ़ंक्शन operator[]() at() पहली कॉल at() , begin() , rbegin() , end() , या rend()

ये नियम इतने जटिल और सूक्ष्म हैं कि मुझे संदेह है कि कई प्रोग्रामर, यदि कोई हैं, तो एक सटीक सारांश दे सकते हैं। मैं नहीं कर सका।

क्या होगा अगर ओ (1) आवश्यकताओं को नजरअंदाज कर दिया जाए?

यदि operator[] पर सी ++ 11 निरंतर समय आवश्यकताओं को नजरअंदाज कर दिया जाता है, तो basic_string लिए गाय तकनीकी रूप से व्यवहार्य हो सकता है, लेकिन इसे कार्यान्वित करना मुश्किल हो सकता है।

संचालन जो गाय डेटा प्रतिलिपि किए बिना स्ट्रिंग की सामग्री तक पहुंच सकते हैं उनमें शामिल हैं:

  • + माध्यम से Concatenation।
  • << माध्यम से आउटपुट।
  • मानक पुस्तकालय कार्यों के लिए तर्क के रूप में एक basic_string का उपयोग करना।

उत्तरार्द्ध क्योंकि मानक पुस्तकालय को कार्यान्वयन विशिष्ट ज्ञान और संरचनाओं पर भरोसा करने की अनुमति है।

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

एक मुख्य जटिल कारक यह है कि सी ++ 11 basic_string आइटम पहुंच में डेटा प्रतिलिपि (स्ट्रिंग डेटा को साझा नहीं करना) ट्रिगर करना आवश्यक है, लेकिन इसे फेंकने की आवश्यकता नहीं है , उदाहरण के लिए सी ++ 11 §21.4.5 / 3 " फेंकता है: कुछ भी नहीं।" । और इसलिए यह गाय डेटा प्रतिलिपि के लिए एक नया बफर बनाने के लिए सामान्य गतिशील आवंटन का उपयोग नहीं कर सकता है। इसके आस-पास एक तरीका एक विशेष ढेर का उपयोग करना है जहां स्मृति वास्तव में आवंटित किए बिना आरक्षित किया जा सकता है, और उसके बाद स्ट्रिंग मान के प्रत्येक तार्किक संदर्भ के लिए आवश्यक राशि आरक्षित करें। इस तरह के ढेर में आरक्षण और अन-रिजर्वेशन निरंतर समय हो सकता है, ओ (1), और जो राशि पहले से आरक्षित है उसे noexcept कर सकती है, यह noexcept हो noexcept । मानक आवश्यकताओं के अनुपालन के लिए, इस दृष्टिकोण के साथ ऐसा लगता है कि प्रति विशिष्ट आवंटक में ऐसा एक विशेष आरक्षण-आधारित ढेर होना आवश्यक होगा।

टिप्पणियाँ:
¹ const आइटम एक्सेसर एक गाय डेटा प्रतिलिपि को ट्रिगर करता है क्योंकि यह क्लाइंट कोड को डेटा को संदर्भ या पॉइंटर प्राप्त करने की अनुमति देता है, जिसे गैर- const आइटम const द्वारा ट्रिगर किए गए बाद की डेटा प्रतिलिपि द्वारा अमान्य करने की अनुमति नहीं है।

यह मेरी समझ थी कि कॉपी-ऑन-राइट सी ++ 11 में एक अनुरूप std::string को लागू करने का एक व्यवहार्य तरीका नहीं है, लेकिन जब हाल ही में चर्चा में आया तो मैंने खुद को उस कथन का सीधे समर्थन करने में असमर्थ पाया।

क्या मैं सही हूं कि सी ++ 11 std::string गाय आधारित कार्यान्वयन स्वीकार नहीं करता है?

यदि हां, तो क्या यह प्रतिबंध स्पष्ट रूप से नए मानक (कहां) में कहीं कहा गया है?

या यह प्रतिबंध अंतर्निहित है, इस अर्थ में कि यह std::string पर नई आवश्यकताओं का संयुक्त प्रभाव है जो std::string गाय आधारित कार्यान्वयन को रोकता है। इस मामले में, मुझे एक अध्याय में रुचि होगी और 'सी ++ 11 के कविता शैली व्युत्पन्न प्रभावी रूप से गाय आधारित std::string कार्यान्वयन को प्रतिबंधित करता है।'


21.4.2 मूल_स्ट्रिंग कन्स्ट्रक्टर और असाइनमेंट ऑपरेटरों से [string.cons]

basic_string(const basic_string<charT,traits,Allocator>& str);

[...]

2 प्रभाव : तालिका 64 में दर्शाए गए अनुसार क्लास basic_string का ऑब्जेक्ट basic_string । [...]

तालिका 64 सहायक रूप से दस्तावेज करता है कि इस (प्रतिलिपि) कन्स्ट्रक्टर के माध्यम से किसी ऑब्जेक्ट के निर्माण के बाद, this->data() मान के रूप में है:

सरणी की आवंटित प्रतिलिपि के अंतिम तत्व पर अंकित करता है जिसका अंतिम तत्व str.data () द्वारा इंगित किया जाता है

अन्य समान रचनाकारों के लिए समान आवश्यकताएं हैं।


चूंकि अब यह गारंटी है कि स्ट्रिंग्स को संगत रूप से संग्रहीत किया जाता है और अब आपको एक स्ट्रिंग के आंतरिक भंडारण में पॉइंटर लेने की इजाजत दी जाती है, (यानी और स्ट्र [0] जैसे कि यह सरणी के लिए काम करता है), उपयोगी गाय बनाना संभव नहीं है कार्यान्वयन। आपको बहुत सी चीजों के लिए एक प्रतिलिपि बनाना होगा। एक गैर-कॉन्स स्ट्रिंग पर operator[] या begin() का उपयोग begin() लिए भी एक प्रति की आवश्यकता होगी।


यह है, CoW तेजी से तार बनाने के लिए एक स्वीकार्य तंत्र है ... लेकिन ...

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

अन्य कारण यह हैं कि [] ऑपरेटर आपको स्ट्रिंग डेटा वापस कर देगा, बिना किसी स्ट्रिंग को ओवरराइट करने के लिए किसी और सुरक्षा के बिना किसी और को अपरिवर्तित होने की उम्मीद है। यह c_str() और data() पर लागू होता है।

क्विक Google का कहना है कि मल्टीथ्रेडिंग मूल रूप से कारण है कि इसे प्रभावी रूप से अस्वीकार कर दिया गया था (स्पष्ट रूप से नहीं)।

प्रस्ताव कहता है:

प्रस्ताव

हम सभी पुनरावर्तक और तत्व अभिगम संचालन को सुरक्षित रूप से निष्पादन योग्य बनाने का प्रस्ताव देते हैं।

हम अनुक्रमिक कोड में भी संचालन की स्थिरता में वृद्धि कर रहे हैं।

यह परिवर्तन प्रभावी ढंग से कॉपी-ऑन-राइट कार्यान्वयन को अस्वीकार करता है।

के बाद

कॉपी-ऑन-राइट कार्यान्वयन से दूर स्विच के कारण प्रदर्शन में सबसे बड़ा संभावित नुकसान बहुत बड़े पढ़ने वाले ज्यादातर तारों वाले अनुप्रयोगों के लिए स्मृति की बढ़ती खपत है। हालांकि, हम मानते हैं कि उन अनुप्रयोगों के लिए रस्सियां ​​एक बेहतर तकनीकी समाधान हैं, और एक रस्सी प्रस्ताव को पुस्तकालय टीआर 2 में शामिल करने के लिए विचार किया जाना चाहिए।

Ropes एसटीएलपोर्ट और एसजीआई एसटीएल का हिस्सा हैं।





copy-on-write