2008-10-19 3 views
5

में उथली प्रतिलिपि के बारे में प्रश्न कहें कि मेरे पास एक इंट पॉइंटर सदस्य चर "i" के साथ एक संरचना है। मैं एस के डिफ़ॉल्ट कन्स्ट्रक्टर में मैं ढेर पर स्मृति आवंटित करता हूं। बाद में कोड के किसी अन्य भाग में मैं कुछ फ़ंक्शन के मान के द्वारा एस का एक उदाहरण पास करता हूं। क्या मैं यहाँ एक उथली प्रतिलिपि कर रहा हूँ? मान लें कि मैंने किसी भी प्रति रचनाकार या असाइनमेंट ऑपरेटर या एस के लिए कुछ भी लागू नहीं किया है ... केवल डिफ़ॉल्ट कन्स्ट्रक्टर।सी ++

उत्तर

8

@ [don.neufeld.myopenid.com] पर क्या अनुवर्ती करने के लिए, यह केवल एक उथली प्रतिलिपि नहीं है, लेकिन यह या तो (मेमोरी लीक या एक लटकने वाला सूचक) है।

// memory leak (note that the pointer is never deleted) 
class A 
{ 
    B *_b; 
    public: 
    A() 
    : _b(new B) 
    { 
    } 
}; 

// dangling ptr (who deletes the instance?) 
class A 
{ 
    B *_b; 
    public: 
    A() 
    ... (same as above) 

    ~A() 
    { 
    delete _b; 
    } 
}; 

इसे हल करने के लिए, कई विधियां हैं।

कच्चे मेमोरी पॉइंटर्स का उपयोग करने वाले वर्गों में हमेशा एक प्रतिलिपि निर्माता और ऑपरेटर = लागू करें।

class A 
{ 
    B *_b; 
    public: 
    A() 
    ... (same as above) 

    ~A() 
    ... 

    A(const A &rhs) 
    : _b(new B(rhs._b)) 
    { 
    } 

    A &operator=(const A &rhs) 
    { 
    B *b=new B(rhs._b); 
    delete _b; 
    _b=b; 
    return *this; 
}; 

जरूरत नहीं कहने के लिए, यह एक बड़ी दर्द है और वहाँ काफी कुछ बारीकियों सही पाने के लिए कर रहे हैं। मुझे पूरी तरह से यकीन नहीं है कि मैंने इसे यहां किया है और मैंने इसे कुछ बार किया है। भूलें कि आपको सभी सदस्यों की प्रतिलिपि बनाना है - यदि आप बाद में कुछ नए जोड़ते हैं, तो उन्हें भी शामिल करना न भूलें!

अपनी कक्षा में कॉपी कन्स्ट्रक्टर और ऑपरेटर = निजी बनाएं। यह "दरवाजा बंद करें" समाधान है। यह सरल और प्रभावी है, लेकिन कभी-कभी अधिक सुरक्षात्मक है।

class A : public boost::noncopyable 
{ 
    ... 
}; 

कभी कच्चे संकेत का उपयोग करें। यह सरल और प्रभावी है। वहाँ बहुत सारे विकल्प यहां हैं:

  • उपयोग स्ट्रिंग वर्गों के बजाय कच्चे चार संकेत
  • उपयोग std :: auto_ptr, को बढ़ावा देने :: shared_ptr, को बढ़ावा देने :: scoped_ptr आदि

उदाहरण:

// uses shared_ptr - note that you don't need a copy constructor or op= - 
// shared_ptr uses reference counting so the _b instance is shared and only 
// deleted when the last reference is gone - admire the simplicity! 
// it is almost exactly the same as the "memory leak" version, but there is no leak 
class A 
{ 
    boost::shared_ptr<B> _b; 
    public: 
    A() 
    : _b(new B) 
    { 
    } 
}; 
+0

आपका असाइनमेंट ऑपरेटर अपवाद सुरक्षित नहीं है। कॉपी और अपवाद सुरक्षा के बारे में हालिया प्रश्न देखें: http://stackoverflow.com/questions/214891/checklist-for-writing-copy-constuctor-and-assignment-operator-in-c#214966 –

+0

दोह, ठीक है मैंने तय किया । आप देखते हैं कि इसका दर्द और मुश्किल होने के बारे में मेरा क्या मतलब है, तो –

+0

कॉपी कन्स्ट्रक्टर और ऑपरेटर = निजी बनाने का सबसे अच्छा तरीका बूस्ट :: noncopyable से प्राप्त करना है। आपको यह तब तक करना चाहिए जब तक कि आप निश्चित रूप से यह सुनिश्चित न करें कि यह प्रतिलिपि होगी। – CesarB

5

हां, यह एक उथली प्रतिलिपि है। अब आपके पास दो प्रतियां हैं (कॉलर में से एक, एक पैरामीटर के रूप में ढेर पर), प्रत्येक जिसमें स्मृति के उसी ब्लॉक में पॉइंटर होता है।

2

आप s struct की दो प्रतियां, जिनमें से प्रत्येक अपने स्वयं के i सूचक होगा, लेकिन दोनों i संकेत होगा एक ही मूल्य की स्मृति में एक ही पते की ओर इशारा करते होगा - तो हाँ, यह एक उथले प्रति रहेगी ।