मुझे पता है कि वेक्टर तत्व विनाश आदेश सी ++ मानक द्वारा परिभाषित नहीं किया गया है (Order of destruction of elements of an std::vector देखें) और मैंने देखा कि मैंने जो सभी कंपाइलर चेक किए हैं, वे इस विनाश को शुरू से अंत तक करते हैं - जो मुझे गतिशील और स्थैतिक सरणी के विपरीत में आश्चर्यजनक है क्योंकि यह विपरीत है ऑर्डर, और यह रिवर्स ऑर्डर अक्सर सी ++ दुनिया में होता है।क्या वेक्टर तत्वों के विनाश आदेश को परिभाषित करना उचित होगा?
सख्त होने के लिए: मुझे पता है कि "कंटेनर सदस्यों ... का निर्माण और नष्ट करने के लिए किसी भी क्रम में नष्ट किया जा सकता है उदाहरण के लिए सम्मिलित करें और सदस्य कार्यों को मिटाना" और मैं इनके लिए किसी प्रकार का लॉग रखने के लिए कंटेनरों को वोट नहीं देता परिवर्तन"। मैं आगे के विनाश से मौजूदा वेक्टर विनाशक कार्यान्वयन को तत्वों के पिछड़े विनाश के लिए बदलने के लिए वोट दूंगा - कुछ और नहीं। और शायद यह नियम सी ++ मानक में जोड़ें।
और कारण क्यों? सरणी से वेक्टर में बदलना इस तरह से सुरक्षित होगा।
असली दुनिया का उदाहरण: हम सभी जानते हैं कि म्यूटेक्स लॉकिंग और ऑर्डर अनलॉक करना बहुत महत्वपूर्ण है। और यह सुनिश्चित करने के लिए कि अनलॉकिंग होता है - स्कोपगार्ड पैटर्न का उपयोग किया जाता है। फिर विनाश आदेश महत्वपूर्ण है। इस उदाहरण पर विचार करें। वहाँ - वेक्टर कारणों गतिरोध को सरणियों से स्विच - सिर्फ इसलिए कि उनके विनाश क्रम भिन्न होता है:
class mutex {
public:
void lock() { cout << (void*)this << "->lock()\n"; }
void unlock() { cout << (void*)this << "->unlock()\n"; }
};
class lock {
lock(const mutex&);
public:
lock(mutex& m) : m_(&m) { m_->lock(); }
lock(lock&& o) { m_ = o.m_; o.m_ = 0; }
lock& operator = (lock&& o) {
if (&o != this) {
m_ = o.m_; o.m_ = 0;
}
return *this;
}
~lock() { if (m_) m_->unlock(); }
private:
mutex* m_;
};
mutex m1, m2, m3, m4, m5, m6;
void f1() {
cout << "f1() begin!\n";
lock ll[] = { m1, m2, m3, m4, m5 };
cout <<; "f1() end!\n";
}
void f2() {
cout << "f2() begin!\n";
vector<lock> ll;
ll.reserve(6); // note memory is reserved - no re-assigned expected!!
ll.push_back(m1);
ll.push_back(m2);
ll.push_back(m3);
ll.push_back(m4);
ll.push_back(m5);
cout << "f2() end!\n";
}
int main() {
f1();
f2();
}
आउटपुट - f1() के लिए f2()
f1() begin!
0x804a854->lock()
0x804a855->lock()
0x804a856->lock()
0x804a857->lock()
0x804a858->lock()
f1() end!
0x804a858->unlock()
0x804a857->unlock()
0x804a856->unlock()
0x804a855->unlock()
0x804a854->unlock()
f2() begin!
0x804a854->lock()
0x804a855->lock()
0x804a856->lock()
0x804a857->lock()
0x804a858->lock()
f2() end!
0x804a854->unlock()
0x804a855->unlock()
0x804a856->unlock()
0x804a857->unlock()
0x804a858->unlock()
आईएमएचओ विनाश आदेश से कोई फर्क नहीं पड़ता कि सॉफ्टवेयर अच्छी तरह डिज़ाइन किया गया है। जब एक विनाशक कहा जाता है, तो इसका मतलब है कि वस्तुओं का उपयोग या आवश्यक नहीं है। आपको यह सुनिश्चित करना चाहिए कि आपकी वस्तुएं एक स्थायी स्थिति में हैं (इस मामले में अब इनका उपयोग नहीं किया गया है) उन्हें नष्ट करने से पहले। – m0skit0
हम सभी जानते हैं कि जब निष्पादन का आदेश महत्वपूर्ण है, तो उन्हें किसी भी कंटेनर में रखना और उत्पन्न कोड को नष्ट करना अच्छा नहीं है। // कारावास नोटिस: मैं "हम सभी जानते हैं" बयान – stefaanv
के साथ थोड़ा संदिग्ध हूं शायद आपने पढ़ने के बिना उत्तर दिया। एन स्कोपगार्ड (http://stackoverflow.com/questions/48647/does-scopeguard-use-really-lead-to-better-code) मैंने यहां उपयोग किया, विनाश आदेश मायने रखता है। यही कारण है कि मैंने इस उदाहरण का इस्तेमाल किया। – PiotrNycz