2009-10-19 30 views
14

मुझे कोड के साथ कई बार सामना करना पड़ता है जहां std :: vector के वर्ग सदस्य के std :: vector :: clear() को कन्स्ट्रक्टर और विनाशक में बुलाया जाता है।std :: vector :: clear() कन्स्ट्रक्टर और विनाशक में

मुझे नहीं क्यों यह आवश्यक है:

  1. निर्माता - प्रकार एसटीडी के वर्ग के सदस्य :: वेक्टर डिफ़ॉल्ट रूप से रिक्त है, तो कोई स्पष्ट कॉल करने के लिए की जरूरत है()।
  2. विनाशक - प्रकार std :: वेक्टर के वर्ग सदस्य को उस वस्तु के मानक विनाश के हिस्से के रूप में नष्ट कर दिया जाएगा। वेक्टर विनाश के हिस्से के रूप में सभी मूल्य ऑब्जेक्ट्स इसमें शामिल किया जाएगा (यदि यह आवंटित पॉइंटर्स को स्मृति में ढेर करता है, तो उन्हें "मैन्युअल रूप से हटाया जाना चाहिए"), इसलिए फिर स्पष्ट() को कॉल करने की आवश्यकता नहीं है।

क्या मुझे कुछ याद आती है?

उत्तर

16

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

5

नहीं, आप सही हैं। जब तक निर्माता में कुछ अतिरिक्त व्यापार (या आधार वर्ग के निर्माता) है कि आवश्यकता है कि है, लेकिन संभावना है कि बहुत कम हैं ...

बाद में संपादित

नाशक के मामले में, में से एक है मैंने देखा कि सबसे आम गलतियों यह है कि कुछ लोग मानते हैं कि स्पष्ट विधि पॉइंटर्स (वेक्टर) के वैक्टरों के लिए भी कॉल को कॉल करेगी, जो निश्चित रूप से

22

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

+2

अच्छा शब्द, 'वूडू प्रोग्रामिंग' :) – xtofl

+7

शून्य पर पॉइंटर सेट करना वूडू नहीं है, यह डिबगिंग में काफी मदद करता है। आपको एक ही पॉइंटर को दो बार हटाने से रोकता है, लेकिन कोई भी ऐसा नहीं करता है - है ना? –

+12

यदि कुछ भी है, तो आप जानना चाहते हैं कि आपने दो बार एक ही पॉइंटर हटा दिया है। –

7
  1. यह की पूरी तरह से एक निर्माता
  2. यह एक नाशक जब तक कंटेनर एक सूचक होता है में एक STL कंटेनर की सामग्री को स्पष्ट करने के लिए unnessecary है में एक STL कंटेनर की सामग्री को स्पष्ट करने के लिए unnessecary। यदि सूचक नया का उपयोग करके बनाया गया है, तो इसे अभी भी हटा दिया जाना चाहिए। इसके बाद भी यह कंटेनर को साफ़ करने के लिए नस्लीय नहीं होगा।

इस पर विचार करें:

#define BOOST_TEST_MODULE StlContainers 
#define BOOST_LIB_DIAGNOSTIC 

#include <boost/test/unit_test.hpp> 
#include <boost/assign.hpp> 
#include <boost/assign/list_of.hpp> 
#include <boost/assign/std/vector.hpp> 

#include <vector> 

using namespace boost::assign; 
using namespace std; 

const vector<int> my_ints_vector = list_of(0)(1)(1)(2)(3)(5)(8)(13)(21)(34); 

struct ScopedStruct1 
{ 
     ScopedStruct1(const vector<int> & v) : m_v(v) {} 
     ~ScopedStruct1() {} 
    private : 
     vector<int> m_v; 
}; 

class A 
{ 
    public : 
     A(int i) : m_i(i) {} 
     ~A() {} 
    private : 
     int m_i; 
}; 

struct ScopedStruct2 
{ 
    ScopedStruct2() {} 
    ~ScopedStruct2() { for(vector<A*>::iterator it = m_v.begin(); it != m_v.end(); ++it) delete *it; } 

    vector<A*> m_v; 
}; 

struct ScopedStruct3 
{ 
    ScopedStruct3() {} 
    ~ScopedStruct3() { /* no deletion */ } 

    vector<A*> m_v; 
}; 

BOOST_AUTO_TEST_CASE(StlContainer_storing_something_simple) 
{ 
    ScopedStruct1 str(my_ints_vector); 
} 

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_with_delete) 
{ 
    ScopedStruct2 str; 
    for(int i = 0; i < 10; i++) 
     str.m_v.push_back(new A(i)); 
} 

BOOST_AUTO_TEST_CASE(StlContainer_storing_pointers_without_delete) 
{ 
    ScopedStruct3 str; 
    for(int i = 0; i < 10; i++) 
     str.m_v.push_back(new A(i)); 
} 

बढ़ावा के unit_test ढांचे का उपयोग करते हुए मैं 3 परीक्षण मामलों बना लिया है। यूनिट_टेस्ट फ्रेमवर्क गेटेट है क्योंकि यह मेमोरी लीक ट्रैक करता है। आप देखेंगे कि पहला और दूसरा टेस्ट केस स्मृति रिसाव उत्पन्न नहीं करता है, लेकिन तीसरा मामला इसलिए करता है क्योंकि वेक्टर की सामग्री हटाई नहीं जाती है।।

+0

उदाहरण कोड के साथ एकमात्र जवाब .. अच्छा! – nkint

-4

पाठ्यक्रम एक का ) स्पष्ट फोन (या आकार बदलने (0) या समकक्ष कहते हैं (std :: _ Destroy_range (...) नाशक में deallocating से पहले

आवंटन रद्द करने संभाजक माध्यम से किया जाता है: : पुनःआवंटन जो किसी भी विनाशकर्ता चलाने नहीं है यह सिर्फ स्मृति को मुक्त कर देते

स्पष्ट() आकार बदलने के लिए (0) जो आवंटित बफर में बातें पहले आकार पर विनाशकर्ता()

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

+1

नहीं, जब कोई वेक्टर गुंजाइश से बाहर हो जाता है तो विनाशकों को निश्चित रूप से बुलाया जाता है। विनाशकों को फोन नहीं करना कोई समझ नहीं आता है। मेरा सुझाव है कि आप अपने कार्यान्वयन की सावधानीपूर्वक जांच करें।आप कुछ इस तरह चलाकर इस परीक्षण कर सकते हैं: # शामिल # शामिल struct टेस्ट {~ टेस्ट() {std :: अदालत << "अलविदा, दुनिया \ n"; }}; int मुख्य() {std :: cout << "बनाना \ n"; std :: वेक्टर टी (1); std :: cout << "बनाया गया \ n"; } – janm

+5

बिल्कुल गलत। –

+0

मैंने उसे उपयोगकर्ता परिभाषित वर्ग के एक वेक्टर सदस्य इंस्टेंस वैरिएबल पर एक स्पष्ट कॉल की चर्चा के बजाय ~ वेक्टर() में एक स्पष्ट कॉल पर चर्चा के रूप में पढ़ा - मेरा गलतफहमी। – pgast

1

एकमात्र मामला मैं सोच सकता हूं कि यह कहां उपयोगी होगा जहां विनाश के आदेश और विनाशक यह सुनिश्चित करना चाहता है कि वेक्टर में वस्तुओं को नष्ट कर दिया जाए कुछ और से पहले।

बेशक, कोड की संरचना करने के लिए बेहतर है; हालांकि, यह एक कल्पनीय कारण है।

1

अभी तक जो कहा गया है उसके बावजूद, कम से कम एक परिदृश्य है जब विनाशक में clear को स्पष्ट कॉल आवश्यक हो सकता है।

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

इस मामले में एक उचित दृष्टिकोण मैन्युअल रूप से कुछ महत्वपूर्ण सदस्य उप-प्रोजेक्ट को साफ़ करने के लिए हो सकता है, जब तक कि clean विधियों या ऐसे विधियों को कॉल करके, विनाश आदेश निर्भरता "गायब हो जाती है"। मुझे लगता है कि शायद आपके द्वारा देखा गया कोड रणनीतिक रूप से चयनित vector सबोबजेक्ट पर clean पर कॉल करके समस्या का समाधान करने के लिए हल करने का प्रयास कर रहा था।

कन्स्ट्रक्टर में clean पर कॉल करने के लिए ... मुझे नहीं पता कि कोई ऐसा कुछ क्यों करेगा।

+0

जाहिर है आप बहुत ही यथार्थवादी शब्द में रहते हैं :) हर बार जब मैंने कोड की जांच की, तो उसने कन्स्ट्रक्टर/विनाशक में "साफ" प्राप्त करने की कोशिश की। आपके द्वारा वर्णित स्थिति के संबंध में, मैं शायद ही इसकी कल्पना कर सकता हूं। इससे बचने के लिए सबसे अच्छा किया जाना चाहिए और यदि संभव नहीं है तो – dimba

+0

पर अच्छी तरह से टिप्पणी की जानी चाहिए, लेकिन मैं गलत हो सकता हूं, लेकिन जब एसएलएल ऑब्जेक्ट स्कोप के अंत में मर रहा है - उदाहरण के लिए। यह वस्तु के विनाशक को भीतर बुलाता है। यदि वह कहा गया वस्तु भी एक एसटीएल कंटेनर है तो इसे स्वचालित रूप से भी स्वयं को साफ़ करना चाहिए। असाधारण स्थिति "नए" द्वारा शुरू किए गए सूचक के साथ उत्पन्न होगी - सामान्य – Maciek

+1

@ मैसीक के रूप में: कोई भी इसके साथ बहस नहीं करता है। मैं फिर से कह रहा हूं कि उस * स्वचालित * सफाई का आदेश कुछ मामलों में अस्वीकार्य हो सकता है। स्वत: सफाई शुरू होने से पहले आपको किस मामले में अपना खुद का, कस्टम ऑर्डर प्री-क्लीनअप करना पड़ सकता है। – AnT

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