वाह, धीमा हो गया!
आप अपनी याददाश्त के साथ कुछ सुंदर पागल चीजें कर रहे हैं, तो चलिए शुरुआत से शुरू करते हैं।
आपके पास एक एकल वेक्टर है जिसमें इसमें 3 तत्व हैं। आप एक संकेतक का उपयोग कर उस वेक्टर का संदर्भ देना चाहते हैं। चलो देखते हैं कि यह कैसा दिखता है:
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// No no no no! You don't have to `new` a pointer that
// you're going to assign to something else!
// This is called a memory leak, and it means you've just wasted (!!!)
// C++ memory! Don't do it
// vector<double>* new_mv_pt = new vector<double> (3);
// Instead, do this:
vector<double>* ptr_to_mv = &mv; // No leak, immediately points to a vector<double> mv;
यह पहली बिट का ख्याल रखता है। अब, चलो थोड़ा गहरा हो जाओ। आप वैक्टरों के संदर्भों का एक वेक्टर स्टोर करना चाहते हैं। ठीक है, यह उचित लगता है। इसके बारे में जाने के कुछ तरीके हैं।के mv
का उदाहरण और अन्य चीजों पर वापस चलते हैं: अपने कोड में इस बिंदु पर
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
vector<double>* ptr_to_mv = &mv;
// So far so good. Now, based on your question, you want
// to have a list of these to point to. So:
vector<vector<double>*> vop;
vop.push_back(ptr_to_mv); // All clean.
, आप तो आप इसे भिन्नता *
या उपयोग के साथ, एक vector<double>*
को पाने के लिए .at()
या operator[]
साथ vop
का उपयोग करना ->
सीधे इस पर काम करने के लिए:
std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at(0) << std::endl; // Prints '233'
यह प्रिंट 233 क्योंकि यह सब आप mv
संदर्भित कर रहा है। एक और जवाब में एक टिप्पणी में, आपने कहा कि जब आप इन पॉइंटर्स को हटाते हैं, तो आपको एक दावा मिलता है। ऐसा होने वाला है, क्योंकि आप चीजों को दो बार हटा रहे हैं!
mv
याद रखें, जिसे आपने बहुत समय पहले घोषित किया था? खैर, आपने इसे गतिशील वेक्टर नहीं बनाया है। आपने new
नहीं किया था, और यह कोई सूचक नहीं है। तो जब फ़ंक्शन निकलता है, तो यह स्वचालित रूप से स्वयं को हटा देगा - यह अपने विनाशक को कॉल करेगा और स्टैक पर मर जाएगा। यदि आप ptr_to_vector
या ptr_to_mv
पर देखते हैं, तो वे सभी mv
का संदर्भ दे रहे हैं, जो स्वयं को साफ़ करता है।
आप उस पर हटाने के फोन हैं, तो आप mv
पर हटाने के कॉल करने के लिए कोशिश कर रहे हैं और आप डबल हटा रहे हैं (यह है कि आप के लिए क्या इशारा कर रहे हैं)!
तो, जब आपके पास mv
पर पॉइंटर है, तो इसे हटाएं। यह एक स्टैक-आधारित चर है। यह खुद को साफ कर देगा।
अभी भी निम्नलिखित है? बढ़िया है, थोड़ा अधिक के इसे में मिलता है:
अब, वहाँ एक कारण आप (एक वेक्टर, आप एक पुराने सूचक के साथ ओवरराइड नहीं सौंपते हैं अप new
की जरूरत के रूप में मैं आप से पहले कहा था कि अगर, आप स्मृति छोड़ देंगे)।
// Our vector of double vector pointers
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back(ptr_to_mv);
// Makes a fresh copy of mv. You must delete this
// manually
vector<double>* fresh_ptr = new vector<double>(mv);
(*fresh_ptr)[0] = 1337;
// changes only data in fresh_ptr, not `mv`
vop.push_back(fresh_ptr);
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
delete fresh_ptr;
//delete ptr_to_mv; // NO.
//delete vop[0]; // NO!
//delete vop[1]; // ... Already deleted from fresh_ptr
// ... This is going to get tedious if we don't have a fresh_ptr
// for every vector we need!
ऊपर समस्या दिखाता है:: आप एक पूरी तरह से नए सिरे से नई सूचक बनाने के हम, दोनों vop
है, जहां एक, हटाने को फोन करके साफ किए जाने की आवश्यकता के अंदर और एक अन्य जो ऐसा नहीं करता 2 संकेत है यह सिर्फ इसलिए है क्योंकि mv
का संदर्भ, जो स्वचालित रूप से साफ़ हो जाता है! वेक्टर पर लूपिंग और सब कुछ हटाने से उस ग़लत दावे का कारण बन जाएगा। हम इसके साथ कैसे निपट सकते हैं और अभी भी हमें साफ-सफाई की आवश्यकता है?
गंदा और त्वरित समाधान 1 delete vop[1]
/fresh_ptr
और इसके साथ किया जाना चाहिए। बेहतर समाधान यह है कि, जब भी आप new
संसाधन बनाते हैं, तो आप इसे std::unique_ptr
नामक इस अद्भुत चीज़ में लपेटते हैं। कोड इस तरह दिखेगा:
// Our vector of double vector pointers. Non-owning
vector<vector<double>*> vop;
vector<double> mv;
mv.push_back(233);
mv.push_back(234);
mv.push_back(654);
// References a stack variable: don't delete
vector<double>* ptr_to_mv = &mv;
vop.push_back(ptr_to_mv);
// Makes a fresh copy of mv
// puts it inside a std::unique_ptr,
// which, like a stack-based vector,
// can clean itself up
std::unique_ptr<vector<double>> fresh_ptr(new vector<double>(mv));
vop.push_back(fresh_ptr.get());
/* Blah blah blah, work */
// Functions about to exit, gotta clean up!
//delete fresh_ptr; // Not necessary
//delete ptr_to_mv; // Nope.jpg
और वहाँ तुम जाओ, जो कुछ टिप्पणी की बाहर कोड को हटा दें और अचानक, अपना सामान एक सीटी के रूप में साफ है!
बेशक, अब, अंतिम सवाल मैं तुम्हारे लिए है: क्या हो आपको लगता है कि कर रहे हैं वैक्टर की संकेत के संदर्भ की ओर इशारा करने के लिए इन सभी संकेत की आवश्यकता है?
सबसे पहले, अपना उत्तर प्राप्त करें। दूसरा, यह महसूस करें कि यह एक भयानक विचार है क्योंकि आप अपने लिए स्मृति का प्रबंधन करने की वेक्टर की क्षमता को समाप्त कर रहे हैं, जो इसे कम से कम उपयोग करने के आधे बिंदु (कम से कम) है। –
मैं सिर्फ यह पता लगाने की कोशिश कर रहा हूं कि उसके पास पहले स्थान पर वेक्टर का सूचक क्यों है। यह ऐसा करने के लिए कोई वैचारिक अर्थ नहीं बनाता है, खासकर यदि यह एक ही कार्य/वर्ग में है। –