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


117

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

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

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

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


5
उनके गाय स्ट्रिंग के लिए GCC बग gcc.gnu.org/bugzilla/show_bug.cgi?id=21334#c45 है । नए सी + 11 11 संकलित कार्यान्वयन का उपयोग करने वाले बगों में से एक :: स्ट्रैड ऑफ लिबस्टीडेक
user7610

जवाबों:


120

इसकी अनुमति नहीं है, क्योंकि मानक 21.4.1 p6 के अनुसार, पुनरावृत्तियों / संदर्भों को अमान्य करने की अनुमति है

- एक तर्क के रूप में गैर-कास्ट basic_string के संदर्भ में लेते हुए किसी भी मानक लाइब्रेरी फ़ंक्शन के तर्क के रूप में।

- ऑपरेटर [], को छोड़कर, सामने, पीछे, शुरू, rbegin, अंत, और रेंडर को छोड़कर गैर-कास्ट सदस्य कार्यों को कॉल करना।

एक गाय स्ट्रिंग के लिए, गैर-कॉन्स्टेबल operator[]को कॉल करने के लिए एक प्रति (और संदर्भों को अमान्य करने) की आवश्यकता होती है, जो ऊपर दिए गए पैराग्राफ द्वारा अस्वीकृत है। इसलिए, C ++ 11 में गाय का तार होना कानूनी नहीं है।


4
कुछ औचित्य: N2534
MM

8
-1 तर्क में पानी नहीं है। एक गाय की नकल के समय कोई संदर्भ या पुनरावृत्तियाँ नहीं हैं जिन्हें अमान्य किया जा सकता है, नकल करने का पूरा बिंदु यह है कि ऐसे संदर्भ या पुनरावृत्तियाँ अब प्राप्त की जा रही हैं, इसलिए प्रतिलिपि आवश्यक है। लेकिन यह अभी भी हो सकता है कि C ++ 11 को लागू न करे।
चीयर्स एंड हीथ। - अल्फ

11
@ चेरसन्ध।-अल्फ: तर्क को निम्न में देखा जा सकता है अगर गाय को अनुमति दी गई हो: std::string a("something"); char& c1 = a[0]; std::string b(a); char& c2 = a[1]; c1 a का संदर्भ है। आप फिर "कॉपी" ए। फिर, जब आप दूसरी बार संदर्भ लेने का प्रयास करते हैं, तो इसे एक गैर-कॉन्स्टेबल संदर्भ प्राप्त करने के लिए एक प्रतिलिपि बनाना पड़ता है क्योंकि दो तार हैं जो एक ही बफर को इंगित करते हैं। इसे पहले लिए गए संदर्भ को अमान्य करना होगा, और ऊपर उद्धृत अनुभाग के खिलाफ है।
डेव एस

9
@ Cheersandhth.-Alf, के अनुसार इस , कम से कम जीसीसी के गाय कार्यान्वयन करता करते Daves वास्तव में क्या कह रहा है। कम से कम गाय की शैली मानक द्वारा निषिद्ध है।
तेवियन बार्न्स

4
@ शेल्फ: यह उत्तर तर्क देता है कि गैर-कास्ट operator[](1) को एक प्रतिलिपि बनाना होगा और यह (2) ऐसा करना अवैध है। आप उन दो बिंदुओं में से किससे असहमत हैं? आपकी पहली टिप्पणी को देखते हुए, ऐसा लगता है कि एक कार्यान्वयन स्ट्रिंग को साझा कर सकता है, कम से कम इस आवश्यकता के तहत, ऊपर जब तक इसे एक्सेस नहीं किया जाता है, लेकिन एक्सेस को पढ़ने और लिखने दोनों को इसे खोलना होगा। क्या वह आपका तर्क है?
बेन वोइगट

48

द्वारा जवाब डेव एस और gbjbaanb हैं सही । (और ल्यूक डैंटन की बात भी सही है, हालांकि यह मूल नियम के बजाय इसे रोकने वाले गाय के तार का एक साइड-इफेक्ट अधिक है।)

लेकिन कुछ भ्रम को दूर करने के लिए, मैं कुछ और विस्तार जोड़ने जा रहा हूं। विभिन्न टिप्पणियाँ GCC Bugzilla पर मेरी एक टिप्पणी से जुड़ी हैं जो निम्नलिखित उदाहरण देती हैं:

std::string s("str");
const char* p = s.data();
{
    std::string s2(s);
    (void) s[0];
}
std::cout << *p << '\n';  // p is dangling

उस उदाहरण का बिंदु यह प्रदर्शित करना है कि CCC 11 में GCC का संदर्भ क्यों गिना गया (गाय) स्ट्रिंग मान्य नहीं है। C ++ 11 मानक को सही ढंग से काम करने के लिए इस कोड की आवश्यकता होती है। कोड में कुछ भी pC ++ 11 में अमान्य होने की अनुमति नहीं देता है ।

जीसीसी के पुराने संदर्भ बार गणना का उपयोग std::stringकार्यान्वयन, कि कोड क्योंकि अपरिभाषित व्यवहार है, p है अवैध, एक dangling सूचक बन गया। (क्या होता है कि जब s2इसका निर्माण किया जाता है तो यह डेटा के साथ साझा करता है s, लेकिन एक गैर-कॉन्स्टेबल संदर्भ प्राप्त करने के s[0]लिए डेटा को अनसर्डेड करना sपड़ता है , इसलिए "राइट ऑन कॉपी" होता है क्योंकि संदर्भ s[0]को संभवतः लिखने के लिए उपयोग किया जा सकता है s, फिर s2जाता है दायरे से बाहर, द्वारा इंगित की गई सरणी को नष्ट करना p)।

C ++ 03 मानक स्पष्ट रूप से 21.3 [lib.basic.string] p5 में उस व्यवहार की अनुमति देता है, जहां यह कहता है कि data()पहली कॉल के बाद कॉल operator[]()पॉइंटर्स, संदर्भों और पुनरावृत्तियों को अमान्य कर सकता है। इसलिए GCC का गाय स्ट्रिंग एक मान्य C ++ 03 कार्यान्वयन था।

C ++ 11 मानक अब उस व्यवहार को अनुमति नहीं देता है, क्योंकि कोई भी कॉल operator[]()पॉइंटर्स, संदर्भ या पुनरावृत्तियों को अमान्य नहीं कर सकता है, भले ही वे किसी कॉल का अनुसरण करें data()

तो ऊपर का उदाहरण C ++ 11 में काम करना चाहिए , लेकिन libstdc ++ की तरह के COW स्ट्रिंग के साथ काम नहीं करता है , इसलिए C ++ 11 में उस तरह के COW स्ट्रिंग की अनुमति नहीं है।


3
एक कार्यान्वयन जो कि .data()(और पॉइंटर, संदर्भ, या पुनरावृत्ति के प्रत्येक रिटर्न पर) कॉल को अनिश्चित करता है, उस समस्या से ग्रस्त नहीं होता है। Ie (अपरिवर्तनीय) एक बफर किसी भी समय अनसेंडेड है, या फिर कोई बाहरी रेफ के साथ साझा नहीं किया गया है। मुझे लगा कि आपने इस उदाहरण के बारे में एक अनौपचारिक बग रिपोर्ट-ए-टिप्पणी के रूप में टिप्पणी की थी, यह गलतफहमी के लिए बहुत खेद है! लेकिन जैसा कि आप इस तरह के कार्यान्वयन पर विचार करके देख सकते हैं जैसा कि मैं यहाँ वर्णन करता हूं, जो noexceptआवश्यकताओं की अनदेखी किए जाने पर C ++ 11 में ठीक काम करता है , उदाहरण औपचारिक के बारे में कुछ भी नहीं कहता है। यदि आप चाहें तो मैं कोड प्रदान कर सकता हूं।
चीयर्स एंड हीथ। - अल्फ

7
यदि आप स्ट्रिंग तक लगभग हर पहुंच को अनशेयर करते हैं तो आप साझा करने के सभी लाभ खो देते हैं। एक मानक कार्यान्वयन के लिए मानक पुस्तकालय के लिए व्यावहारिक होना आवश्यक है std::string, और मुझे पूरी तरह से संदेह है कि आप एक उपयोगी, प्रदर्शनकारी गाय स्ट्रिंग दिखा सकते हैं जो C ++ 11 अमान्य आवश्यकताओं को पूरा करता है। इसलिए मैं यह सुनिश्चित noexceptकरता हूं कि अंतिम समय में जो विनिर्देशन जोड़े गए हैं, वे गाय के तंत्र को प्रतिबंधित करने का परिणाम हैं, अंतर्निहित कारण नहीं। N2668 पूरी तरह से स्पष्ट प्रतीत होता है, आप समिति की मंशा के स्पष्ट प्रमाणों का खंडन क्यों करते रहते हैं?
जोनाथन वेकली

यह भी याद रखें कि data()एक कॉन्स्टेबल सदस्य कार्य है, इसलिए अन्य कॉन्स्टेबल सदस्यों के साथ समवर्ती कॉल करने के लिए सुरक्षित होना चाहिए, और उदाहरण के लिए data()समवर्ती रूप से कॉल करने के लिए अन्य थ्रेड की प्रतिलिपि बनाना। इसलिए आपको हर स्ट्रिंग ऑपरेशन के लिए म्यूटेक्स के सभी ओवरहेड की आवश्यकता है , यहां तक ​​कि कॉन्स्टेंस या लॉक-फ्री म्यूटेबल रेफरेंस-काउंटेड स्ट्रक्चर की जटिलता, और उसके बाद आपको केवल तभी शेयरिंग मिलेगी जब आप कभी संशोधित या एक्सेस नहीं करेंगे। आपके तार, इतने सारे, कई तार एक के संदर्भ-गणना होंगे। कृपया कोड प्रदान करें, noexceptगारंटी को अनदेखा करने के लिए स्वतंत्र महसूस करें ।
जोनाथन वेकली

2
बस कुछ कोड को एक साथ मिलाने से अब मुझे पता चला कि 129 basic_stringसदस्य कार्य कर रहे हैं , साथ ही मुफ्त कार्य भी। अमूर्त लागत: यह ऑफ-द-कफ गैर-अनुकूलित ताजा ज़रोथ संस्करण कोड जी + ++ और एमएसवीसी दोनों के साथ 50 से 100% धीमा है। यह थ्रेड सेफ्टी (आसान पर्याप्त लीवरेजिंग shared_ptr, मुझे लगता है) नहीं करता है और यह केवल समय के प्रयोजनों के लिए एक शब्दकोश को छाँटने के लिए पर्याप्त है, लेकिन मोडुलो बग्स यह साबित करता है कि basic_stringसी ++ noexceptआवश्यकताओं को छोड़कर एक संदर्भ की अनुमति दी गई है । github.com/alfps/In-principle-demo-of-ref-counted-basic_string
चीयर्स और हीथ। - अल्फ


20

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

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

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

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

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

प्रस्ताव

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

हम अनुक्रमिक कोड में भी संचालन की स्थिरता बढ़ा रहे हैं।

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

के बाद

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

रस्सियाँ STLPort और SGI STL का हिस्सा हैं।


2
ऑपरेटर [] समस्या वास्तव में कोई समस्या नहीं है। कांस्ट वैरिएंट सुरक्षा प्रदान करता है, और नॉन-कास्ट वैरिएंट में उस समय हमेशा सीओडब्ल्यू करने का विकल्प होता है (या वास्तव में पागल होना और इसे ट्रिगर करने के लिए पेज फॉल्ट सेट करना)।
क्रिस्टोफर स्मिथ

+1 मुद्दों पर जाता है।
चीयर्स एंड हीथ। - अल्फ

5
यह सिर्फ मूर्खतापूर्ण है कि एक std :: cow_string वर्ग को lock_buffer (), आदि के साथ शामिल नहीं किया गया था, बहुत बार मुझे पता है कि थ्रेडिंग एक मुद्दा नहीं है। अधिक बार नहीं, वास्तव में।
एरिक एरोनिटी

मुझे एक वैकल्पिक, ig रस्सियों का सुझाव पसंद है। मुझे आश्चर्य है कि यदि कोई अन्य विकल्प उपलब्ध हैं और कार्यान्वयन उपलब्ध हैं।
वोल्टेयर

5

21.4.2 बुनियादी_स्ट्रिंग कंस्ट्रक्टर और असाइनमेंट ऑपरेटरों से [string.cons]

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

[...]

2 प्रभाव : basic_stringतालिका 64 में दर्शाए अनुसार कक्षा की एक वस्तु का निर्माण करता है। [...]

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

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

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


+1 बताते हैं कि कैसे C ++ 11 (कम से कम आंशिक रूप से) गाय को प्रतिबंधित करता है।
चीयर्स एंड हीथ। - अल्फ

क्षमा करें, मैं थक गया था। यह इससे अधिक कुछ भी नहीं समझाता है कि .data () के एक कॉल को ट्रिगर करना चाहिए यदि वर्तमान में बफ़र साझा किया गया हो तो कॉपी करना। फिर भी यह उपयोगी जानकारी है, इसलिए मैंने अपवोट को खड़ा कर दिया।
चीयर्स एंड हीथ। - अल्फ

1

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


1
मुझे लगता है कि C ++ 11 में तार को संचित रूप से संग्रहीत किए जाने की गारंटी है।
mfontanini 15

4
अतीत में आपको उन सभी स्थितियों में कॉपियाँ करनी थीं और यह कोई समस्या नहीं थी ...
डेविड रॉड्रिग्ज़ - drieas

@mfontanini हां, लेकिन वे पहले नहीं थे
डिर्क होलस्पॉप

3
हालांकि C ++ 11 गारंटी देता है कि तार सन्निहित हैं, कि गाय के तार पर प्रतिबंध लगाने के लिए रूढ़िवादी है। GCC का गाय स्ट्रिंग सन्निहित है, इसलिए स्पष्ट रूप से आपका दावा है कि "यह एक उपयोगी गाय कार्यान्वयन संभव नहीं है" फर्जी है।
जोनाथन वैक्ली

1
@supercat, बैकिंग स्टोर के लिए पूछ रहा है (जैसे कॉल करके c_str()) ओ (1) होना चाहिए और फेंक नहीं सकता है, और डेटा दौड़ का परिचय नहीं देना चाहिए, इसलिए यदि आप आलसी रूप से सहमति देते हैं तो उन आवश्यकताओं को पूरा करना बहुत मुश्किल है। व्यवहार में एकमात्र उचित विकल्प हमेशा सन्निहित डेटा को संग्रहीत करना है।
जोनाथन वैक्ली

1

गाय basic_stringC ++ 11 और बाद में निषिद्ध है?

के बारे में

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

हाँ।

के बारे में

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

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

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

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

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

C ++ 11 ++21.4.5 / 4 :

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

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

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


गाय भी C ++ 11 अमान्य नियमों के माध्यम से निषिद्ध है?

एक अन्य उत्तर में, जो लेखन के समय समाधान के रूप में चुना जाता है, और जो भारी रूप से उखाड़ा जाता है और इसलिए स्पष्ट रूप से माना जाता है, यह माना जाता है कि

" एक गाय के लिए स्ट्रिंग, गैर बुला बुला const operator[]एक प्रतिलिपि (और संदर्भों को अमान्य) बनाने की आवश्यकता होगी, जो कि [C ++ 11 quot21.4.1 / 6] के ऊपर [उद्धृत] पैराग्राफ द्वारा अस्वीकृत है। इसलिए, C ++ 11 में गाय का तार होना कानूनी नहीं है।

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

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

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

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

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

C ++ 11 3C.2.11 [diff.cpp03.strings], §21.3 के बारे में:

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

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

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

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

" संदर्भ संकेत दिए गए, और iterators एक के तत्वों की चर्चा करते हुए 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()सदस्य कार्य।
- गैर कॉलिंग constसदस्य काम करता है, को छोड़कर operator[](), at(), begin(), rbegin(), end(), और rend()
- के रूपों को छोड़कर ऊपर का उपयोग करता है में से किसी के बाद insert()और erase()जो गैर करने के लिए iterators लौटने के लिए, पहली कॉल constसदस्य कार्यों operator[](), at(), begin(), , याrbegin() ,end()rend()

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


क्या होगा अगर O (1) आवश्यकताओं की अवहेलना की जाए?

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

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

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

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

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

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


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


3
" आपका उदाहरण गलत- C ++ 11 कार्यान्वयन का एक अच्छा उदाहरण है। संभवतः यह C ++ 03 के लिए सही था।" हाँ यह उदाहरण की बात है । यह एक सीएच स्ट्रिंग दिखाता है जो C ++ 03 में कानूनी था क्योंकि यह पुराने पुनरावृत्ति अमान्य नियमों को नहीं तोड़ता है और C ++ 11 में कानूनी नहीं है क्योंकि यह नए पुनरावृत्ति अमान्य नियम को तोड़ता है। और यह ऊपर दिए गए टिप्पणी में मेरे द्वारा उद्धृत बयान का भी विरोधाभासी है।
जोनाथन वैक्ली

2
यदि आप ने कहा था साझा किए जाने योग्य नहीं शुरू में साझा मैं तर्क दिया है नहीं होगा। कुछ कहना शुरू में साझा करना सिर्फ भ्रम पैदा करना है। खुद के साथ साझा किया? यही शब्द का अर्थ नहीं है। लेकिन मैं दोहराता हूं: आपका तर्क है कि C ++ 11
जोनाथन वैक्ली

5
आपका प्रस्तावित गाय स्ट्रिंग दिलचस्प है, लेकिन मुझे यकीन नहीं है कि यह कितना उपयोगी होगा। गाय स्ट्रिंग की बात केवल उस स्ट्रिंग डेटा की प्रतिलिपि बनाना है जिसमें दो तार लिखे गए हैं। किसी उपयोगकर्ता द्वारा परिभाषित रीड ऑपरेशन होने पर आपके सुझाए गए कार्यान्वयन को कॉपी करने की आवश्यकता होती है। यहां तक ​​कि अगर कंपाइलर केवल एक रीड जानता है , तो भी इसे कॉपी करना होगा। इसके अलावा, एक यूनिक स्ट्रिंग को कॉपी करने से इसके स्ट्रिंग डेटा (संभवत: एक शैरबल स्टेट) की कॉपी हो जाएगी, जो फिर से गाय को बेकार कर देता है। तो जटिलता की गारंटी के बिना, आप लिख सकते हैं ... एक बहुत भद्दा गाय स्ट्रिंग।
निकोल बोलस

2
तो जब आप तकनीकी रूप से सही होते हैं कि जटिलता की गारंटी होती है, जो आपको गाय के किसी भी रूप को लिखने से रोकता है , तो यह वास्तव में [basic.string] / 5 है जो आपको गाय के स्ट्रिंग के किसी भी उपयोगी रूप को लिखने से रोकता है ।
निकोल बोलस

4
@JonathanWakely: (1) आपका उद्धरण सवाल नहीं है। यहाँ सवाल है: "क्या मैं सही हूं कि सी ++ 11 एसटीडी के कार्यान्वयन को आधारित नहीं करता है :: स्ट्रिंग? यदि हां, तो क्या यह प्रतिबंध नए मानक (जहां) में कहीं स्पष्ट रूप से कहा गया है? " (२) आपकी राय कि एक गाय std::string, जब ओ (१) आवश्यकताओं की अवहेलना कर रही है, अक्षम होगी, तो आपकी राय है। मुझे नहीं पता कि प्रदर्शन क्या हो सकता है, लेकिन मुझे लगता है कि इस जवाब के लिए किसी भी प्रासंगिकता की तुलना में, इस विचार को व्यक्त करने के लिए जोर दिया जाता है।
चीयर्स एंड हीथ। -

0

मैं हमेशा अपरिवर्तनीय गायों के बारे में सोच रहा था: एक बार गाय बन जाने के बाद मुझे केवल दूसरी गाय से असाइनमेंट के माध्यम से बदला जा सकता है, इसलिए यह मानक के अनुरूप होगा।

मेरे पास आज एक साधारण तुलना परीक्षण के लिए इसे आजमाने का समय था: प्रत्येक नोड के साथ स्ट्रिंग / गाय द्वारा आकार एन का एक नक्शा (नक्शे में हमारे पास एनएक्सएन वस्तुओं की संख्या) है।

स्ट्रिंग्स के आकार के साथ ~ 300 बाइट्स और एन = 2000 गायें थोड़ी तेज़ होती हैं और लगभग कम स्मृति परिमाण का उपयोग करती हैं। नीचे देखें, आकार kbs में हैं, रन बी गायों के साथ है।

~/icow$ ./tst 2000
preparation a
run
done a: time-delta=6 mem-delta=1563276
preparation b
run
done a: time-delta=3 mem-delta=186384
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.