स्थानांतरित कंटेनर का पुन: उपयोग करना?


84

स्थानांतरित कंटेनर का पुन: उपयोग करने का सही तरीका क्या है?

std::vector<int> container;
container.push_back(1);
auto container2 = std::move(container);

// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize

container.push_back(2);
assert(container.size() == 1 && container.front() == 2);

मैंने C ++ 0x मानक ड्राफ्ट में जो पढ़ा है, उससे; ver3 सही तरीका प्रतीत होता है, क्योंकि किसी वस्तु को चाल में रखने के बाद

"जब तक अन्यथा निर्दिष्ट नहीं किया जाता है, तब तक ऐसी स्थानांतरित वस्तुएं वैध लेकिन अनिर्दिष्ट स्थिति में रखी जाएंगी।"

मुझे कभी कोई उदाहरण नहीं मिला जहां यह "अन्यथा निर्दिष्ट" हो।

हालांकि मुझे ver3 थोड़ा चक्कर लगता है और इसमें बहुत पसंद किया जाने वाला ver1 होगा, हालांकि vec3 कुछ अतिरिक्त अनुकूलन की अनुमति दे सकता है, लेकिन दूसरी तरफ आसानी से गलतियां हो सकती हैं।

क्या मेरी धारणा सही है?


4
आप बस फोन कर सकते हैं clear, क्योंकि इसमें कोई पूर्व शर्त नहीं है (और इस प्रकार वस्तु की स्थिति पर कोई निर्भरता नहीं है)।
निकोल बोलस

@ नाइकोल: मान लीजिए कि एक std::vectorकार्यान्वयन था जिसने एक संकेतक को उसके आकार में संग्रहीत किया (मूर्खतापूर्ण, लेकिन कानूनी लगता है)। उस वेक्टर से चलते हुए पॉइंटर NULL को छोड़ सकते हैं, जिसके बाद clearवह विफल हो जाएगा। operator=भी असफल हो सकता है।
बेन Voigt

9
@ पता: मुझे लगता है कि "वैध लेकिन अनिर्दिष्ट" के "वैध" भाग का उल्लंघन होगा।
०।

1
@ गिल्डरन: मुझे लगा कि इसका मतलब सिर्फ विध्वंसक को चलाना सुरक्षित है।
बेन वोइगट

मुझे लगता है कि सवाल यह है कि "वैध" क्या है?
रॉनग

जवाबों:


97

"मान्य लेकिन अनिर्दिष्ट राज्य" की कल्पना की धारा 17.3.26 से:

एक ऑब्जेक्ट राज्य जो निर्दिष्ट नहीं है सिवाय इसके कि ऑब्जेक्ट के इनवेरिएंट्स मिले हैं और ऑब्जेक्ट पर कार्रवाई अपने प्रकार के लिए निर्दिष्ट के रूप में व्यवहार करती है [उदाहरण: यदि xप्रकार std::vector<int>का ऑब्जेक्ट वैध लेकिन अनिर्दिष्ट राज्य में है, तो x.empty()बिना शर्त के कहा जा सकता है, और x.front()कहा जा सकता है केवल तभी x.empty()रिटर्न झूठी। उदाहरण का]

इसलिए, वस्तु लाइव है। आप किसी भी ऑपरेशन को कर सकते हैं जिसमें एक पूर्व शर्त की आवश्यकता नहीं होती है (जब तक कि आप पहले पूर्व सत्यापन को सत्यापित नहीं करते हैं)।

clear, उदाहरण के लिए, कोई पूर्व शर्त नहीं है। और यह किसी ज्ञात स्थिति में ऑब्जेक्ट को वापस कर देगा। तो बस इसे साफ करें और इसे सामान्य रूप में उपयोग करें।


जहाँ मानक में मैं उदाहरण के लिए "preonditions" के बारे में पढ़ सकता हूँ std :: वेक्टर तरीके?
रॉनग

1
@ronag: .223.2 में वे टेबल हैं जहाँ वे सूचीबद्ध हैं।
ग्रिजली

2
मैंने पाया कि जो दिलचस्प है, open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3241.html , वे लिखते हैं "कंटेनर खाली होने से खाली हो सकते हैं"।
23

4
@ क्रोनग: 1) यदि कंटेनर वैध अवस्था में है तो कॉलिंग clearवैध है। 2) कंटेनर जबकि था एक अनिर्दिष्ट राज्य में, बुला clearडालता है एक निर्दिष्ट राज्य में कंटेनर क्योंकि यह मानक (§23.2.3 तालिका 100) में postconditions सौंपा गया है। std::vector<T>एक वर्ग अपरिवर्तनीय है push_back()जो हमेशा मान्य होता है (जब तक Tहै CopyInsertable)।
ildjarn

3
@ronag: open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3241.html "खाली की तुलना में खाली" उद्धरण पर राष्ट्रीय निकाय टिप्पणियों में से एक को उद्धृत कर रहा था। राष्ट्रीय निकाय की टिप्पणी गलत थी। N3241 ने ऐसे राज्य का प्रस्ताव नहीं किया था। यदि एक std का कार्यान्वयन :: कंटेनर में एक "खाली से खाली राज्य" होता है, जो एक चाल से उत्पन्न होता है, तो उस राज्य का एक वैध राज्य होना चाहिए (अर्थात आप उस वस्तु के साथ कुछ भी कर सकते हैं जिसके लिए कोई पूर्व शर्त की आवश्यकता नहीं है)।
हावर्ड हिनांट

11

ऑब्जेक्ट एक वैध, लेकिन अपरिभाषित स्थिति में होने का मूल रूप से मतलब है कि जबकि ऑब्जेक्ट की सटीक स्थिति की गारंटी नहीं है, यह वैध है और जब तक वे भरोसा नहीं करते तब तक ऐसे सदस्य कार्य (या गैर-सदस्य कार्य) की गारंटी दी जाती है। एक निश्चित राज्य होने वाली वस्तु पर।

clear()सदस्य समारोह वस्तु और इसलिए वस्तुओं से चले गए पर कहा जा सकता है (से है कि यह वैध है, निश्चित रूप से अन्य) की स्थिति पर कोई पूर्व शर्त है। उदाहरण के लिए दूसरी ओर front()कंटेनर खाली नहीं होने पर निर्भर करता है, और इसलिए इसे नहीं बुलाया जा सकता है, क्योंकि यह खाली नहीं होने की गारंटी नहीं है।

इसलिए ver2 और ver3 दोनों ठीक होने चाहिए।


एक वेक्टर हमेशा खाली होगा, लेकिन यह सामान्य मामले का सच नहीं है, (IE सरणी)
Mooing Duck

"एक वेक्टर हमेशा खाली रहेगा", आप उस पर क्या आधार देते हैं?
रॉनग

1
@ क्रोनग: मेरा मतलब था ver2 और ver3 ऑफ कोर्स (जैसा कि टेक्स्ट से स्पष्ट होना चाहिए, तय किया गया कि टाइपो
ग्रिजली

दिलचस्प बात front()यह है कि इसके लिए पूर्व शर्त केवल std::arrayतालिका में नहीं है और यहां तक ​​कि इसके लिए भी बताई गई है।
बेन Voigt

1
@Ben: .223.2.3 तालिका 100 में कहा गया है कि परिचालन शब्दार्थ front()हैं *a.begin(), .223.2.1 / 6 कहते हैं, " यदि कंटेनर खाली है, तोbegin() == end() ", और .224.2.1 / 5 कहते हैं, " पुस्तकालय उस अतीत को कभी नहीं मानता है- अंत-मान माननीय हैं। " नतीजतन मुझे लगता है कि इसके लिए पूर्व शर्त का front()अनुमान लगाया जा सकता है, हालांकि इसे निश्चित रूप से अधिक स्पष्ट किया जा सकता है।
िलजर्न

-8

मुझे नहीं लगता कि आप किसी स्थानांतरित वस्तु से कुछ भी कर सकते हैं (इसे नष्ट करने के अलावा)।

क्या आप swapइसके स्थान पर उपयोग नहीं कर सकते हैं , हिलने के सभी फायदे प्राप्त करने के लिए लेकिन एक ज्ञात स्थिति में कंटेनर को छोड़ दें?


+1। स्वैप एक अच्छा विचार है, हालांकि यह सभी मामलों में काम नहीं करेगा, जैसे ऑटो का उपयोग करना काम नहीं करेगा। शायद एक safe_move, जो आंतरिक रूप से स्वैप का उपयोग करता है एक विचार हो सकता है?
रॉनग

5
यह एक जीवित वस्तु है, और आप ऐसे किसी भी फ़ंक्शंस का उपयोग कर सकते हैं, जिसमें पूर्व-शर्तें नहीं हैं (इनवियर्स से अलग)
आक्रमणकारियों Mooing Duck

प्राथमिक टेम्पलेट के लिए std::swap2 चाल असाइनमेंट हैं, उन असाइनमेंट के लक्ष्यों को मूल्‍यों से स्थानांतरित किया जा रहा है। वह मेरे लिए "एक स्थानांतरित वस्तु से कुछ करने" के रूप में गिना जाता है
Caleth
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.