2009-08-21 21 views
5

मान लें कि मेरे पास एक सामान्य ऑब्जेक्ट क्लास है, और एक सामान्य सूची वर्ग है। मैं इन ऑब्जेक्ट्स की एक सूची बनाए रखना चाहता हूं। क्या मुझे उन्हें List<Object> या List<Object*> के रूप में स्टोर करना चाहिए?ऑब्जेक्ट्स की एक सूची संग्रहीत करना

अगर मैं List<Object> का उपयोग करें और मैं की तरह एक विधि है:

if(some_condition) { 
    Object obj; 
    myObjectList.append(obj); 
} 

और मेरी सूची वर्ग केवल वस्तु के लिए एक संदर्भ इसलिए जैसे ही यह है कि अगर बयान समाप्त हो जाता है, वस्तु नष्ट हो जाता है रहता है, और जिस वस्तु को मैंने धक्का दिया वह अमान्य हो गया। तो फिर मैं कुछ ऐसा कर रहा हूं जैसे:

Object *obj = new Object; 
myObjectList.append(*obj); 

ताकि यह नष्ट न हो जाए। लेकिन अब वस्तुएं अव्यवस्थित हैं, नहीं? क्योंकि अब वे ऑब्जेक्ट्स के रूप में सूची में सुरक्षित रूप से संग्रहीत हैं, ऑब्जेक्ट्स के पॉइंटर्स नहीं, इसलिए मैं उन पर डिलीट नहीं कर सकता ... या जब वे सूची से पॉप हो जाते हैं तो वे स्वचालित रूप से नष्ट हो जाएंगे?

उस स्थिति में, मुझे शायद List<Object*> का उपयोग करना चाहिए और जब मैं उनके साथ किया जाता हूं, तो उन्हें सूची से हटा दें, नहीं?

तो उलझन में ... मुझे यकीन है कि मेरे पास कहीं मौलिक गलतफहमी है।

+0

मुद्दा यह है कि आप प्रोग्रामिंग कर रहे हैं जैसे जावा है ... यह नहीं है। –

+2

वैसे मैं जावा पृष्ठभूमि या कुछ भी नहीं आ रहा हूं ... मैं आज रात थोड़ा मंद हूं। – mpen

उत्तर

6

संपादित करें: के बाद से यह और अधिक कुशल है और एक std::list<boost::shared_ptr<T> > रूप में एक ही शुद्ध प्रभाव पड़ता है एक टिप्पणी boost::ptr_list में उल्लेख किया है और भी बेहतर है।


संपादित करें: आपको लगता है कि आप अपनी टिप्पणी में क्यूटी उपयोग कर रहे हैं का उल्लेख है। आप उपयोग कर रहे हैं> = 4.5 आप इस तरह क्यूटी के QList और QSharedPointer कक्षाओं का उपयोग कर सकते हैं:

QList<QSharedPointer<Object> > object_list; 
object_list.push_back(QSharedPointer<Object>(new Object)); 

मैं तुम्हें std::list<> उपयोग का सुझाव देंगे। आप शायद ऑब्जेक्ट्स को पॉइंटर्स स्टोर करना चाहते हैं ताकि उन्हें हर समय कॉपी नहीं किया जा सके।

तो लब्बोलुआब यह है:

मान लीजिए कि आप एक वर्ग Object नामित करते हैं। आप इस करना चाहिए:

std::list<boost::shared_ptr<Object> > object_list; 
object_list.push_back(new Object); 

C++ 11/14, को बढ़ावा देने के लिए कोई जरूरत नहीं है, बस मानक स्मार्ट संकेत का उपयोग करें:

std::list<std::shared_ptr<Object>> object_list; 
object_list.push_back(std::make_shared<Object>()); 

साझा संकेत का उपयोग करके, वस्तुओं को साफ हो जाएगा स्वचालित रूप से जब उन्हें सूची से निकाल दिया जाता है (यदि कोई अन्य shared_ptr एस भी इंगित नहीं करता है)।

आपके पास list<Object *> हो सकता है। लेकिन आपके अनुभव स्तर को देखते हुए, मुझे लगता है कि आपके लिए काम करने के लिए सूचक संदर्भित सूचक बहुत आसान होगा।

उस मामले में, मैं शायद सूची का उपयोग करें और इन्हें सूची से हटा देना चाहिए जब मैं उन्हें पूरा कर लेने नहीं?

हाँ, यह एक व्यवहार्य विकल्प है, लेकिन मैं अत्यधिक से बचने के लिए "... और इन्हें सूची से हटा ..." पूरी तरह से कदम स्मार्ट संकेत सलाह देते हैं।


नोट:

भी उदाहरण कोड दिया था:

Object *obj = new Object; 
myObjectList.append(*obj); 

शायद नहीं है कि तुम क्या चाहते थे, इस ढेर पर एक नई वस्तु बना देता है, वे एक प्रतिलिपि डालता है सूची में से। यदि उसके बाद delete obj नहीं है, तो आपके पास मेमोरी लीक है क्योंकि कच्चे पॉइंटर्स स्वचालित रूप से delete डी नहीं होते हैं।

+0

ठीक है, मैं QList का उपयोग करना पसंद करूंगा क्योंकि मैं क्यूटी के साथ काम कर रहा हूं। लेकिन मुझे लगता है कि आपका सुझाव अभी भी काम करता है। – mpen

+0

क्यूलिस्ट <> लगभग समान रूप से std :: सूची <> पर काम करेगा। वे दोनों templated हैं और दोनों पॉइंटर्स/स्मार्ट पॉइंटर्स हो सकते हैं। –

+0

क्यूलिस्ट <> एसटीएल स्टाइल इटरेटर्स का भी समर्थन करता है ताकि वे जेनेरिक सी ++ एल्गोरिदम के साथ अच्छे और संगत हों। –

3

पहले मामले में ऑब्जेक्ट की प्रतिलिपि बनाई गई है और केवल मूल नष्ट हो गया है। अन्य उदाहरण सूची में रखा गया है।

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

+0

ओह ... मैं देख रहा था कि क्या हो रहा था। क्योंकि जिस कोड के साथ मैं काम कर रहा हूं, मेरे पास मिश्रण में एक और पॉइंटर फेंक दिया गया है ... मुझे लगता है कि कोई अमान्य था, और कोई नहीं था। इससे बहुत कुछ पता चलता है। – mpen

+2

सुनिश्चित करें कि आपके पास 'गहरी' प्रतिलिपि निर्माता है, या आपको कुछ वास्तव में अप्रत्याशित परिणाम मिल सकते हैं। – DeusAduro

1

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

class Base 
{ 
public: 
    int x; 
    virtual int getData() const { return x; } 
}; 
class Derived : public Base 
{ 
public: 
    int y; 
    virtual int getData() const { return y; } 
}; 

Derived obj1; 
obj1.x = 1; 
obj1.y = 2; 

Base obj2 = obj1; 
cout << obj2.getData(); 

है यही कारण है कि यह, 1 प्रिंट होगा के बाद से obj2 सिर्फ obj1 के आधार भाग की एक प्रति है और वास्तव में बेस का एक उदाहरण है। शैतान का में -

1

आप सूची इस्तेमाल कर सकते हैं, और फिर जब इस पर स्थिति एक्स एक वस्तु पुनःआवंटन करने का समय है, आप कुछ तरह

void erase_object(list* l, int i) { 
    delete (*list)[x] 
    list -> removeObj((*list)[x]); 
} 
2

"सभी" चीजों के साथ के रूप में प्रयोग करेंगे कोई एक जवाब है आप जो करना चाहते हैं उसका विवरण, या आपकी बाधाएं क्या हैं।

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

यदि प्रतिलिपि को कम करने के लिए और अधिक महत्वपूर्ण है, तो टेम्पलेट तत्काल से अनावश्यक कोड को खत्म करें, फिर स्मार्ट, साझा पॉइंटर्स की एक सूची का उपयोग करें।

या नग्न पॉइंटर्स की एक सूची का उपयोग करें, नए/हटाएं का उपयोग करें, और अपने सूचक स्वामित्व के साथ सावधानी बरतें।

कोई भी सूची एक सूची की तरह कार्य करेगी, इसलिए सूची कार्यान्वयन की पसंद उन कारकों पर निर्भर है जिन पर आप यहां गणना नहीं कर रहे हैं।

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