2013-04-15 13 views
5

की ओर इशारा का एक वेक्टर बनाने के लिए मैं एक वेक्टर के लिए एक सूचक है:कैसे एक वेक्टर

vector<double> mv; 
mv.push_back(233); 
mv.push_back(234); 
mv.push_back(654); 
vector<double>* new_mv_pt = new vector<double> (3); 
new_mv_pt = &mv;  

cout << (*new_mv_pt)[1] << endl;  

मैं एक वेक्टर है कि एक सदिश को यह सूचक स्टोर करेगा कैसे बना सकते हैं? मैं इस कोशिश कर रहा था ...

vector<double*> vop = new vector<double> (3); 

vop.push_back(*new_mv_pt); 

cout << (*vop)[1] << endl; 

लेकिन यह काम नहीं किया। है क्या मैं भी संभव प्रयास कर रहा हूँ ?:

+2

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

+0

मैं सिर्फ यह पता लगाने की कोशिश कर रहा हूं कि उसके पास पहले स्थान पर वेक्टर का सूचक क्यों है। यह ऐसा करने के लिए कोई वैचारिक अर्थ नहीं बनाता है, खासकर यदि यह एक ही कार्य/वर्ग में है। –

उत्तर

3

हां, लेकिन आप ऐसा करने की जरूरत:

vector<vector<double>*> vop; 

आप देख रहे हैं क्योंकि वेक्टर संकेत की एक सूची के लिए।

तुम यहाँ है क्या:

vector<double *> vop 

सिर्फ double संकेत का एक वेक्टर है।

इसके अलावा, आप सिर्फ इस चाहते हैं:

vop.push_back(new_mv_pt); // <- No asterisk (you don't want to de-reference it) 
+0

स्मृति में रिसाव से बचने के लिए मैं दोनों पॉइंटर्स को हटाने के बारे में कैसे जाउंगा? मैं new_mv_pt को हटाने का प्रयास करता हूं और मुझे रन टाइम पर किसी प्रकार की दावा त्रुटि मिलती है। समस्या क्या है? –

+0

आप दोनों पॉइंटर्स का क्या मतलब है? क्या आपका मतलब है 'new_mv_pt' और वेक्टर में से एक? –

+0

वैसे जब मैं पॉइंटर्स के वेक्टर में होने के बिना new_mv_pt को हटाने का प्रयास करता हूं, तो यह काम नहीं करेगा और रन टाइम पर किसी प्रकार की दावा त्रुटि के साथ आता है। अंत में मैं जानना चाहता हूं कि इसे सुरक्षित रूप से कैसे हटाएं। –

2

आप एक स्मृति रिसाव यहाँ:,

vector<double>* new_mv_pt = new vector<double> (3); 
new_mv_pt = &mv; 

आप ढेर पर एक vector<double> बना रहे हैं भंडारण पता new_mv_pt में है, और उसके बाद ओवरराइटिंग mv के पते के साथ पता चलता है। vector<double> अभी भी ढेर पर मौजूद है, लेकिन आपने अपना पता स्थायी रूप से खो दिया है (और इसलिए delete पर इसका कोई तरीका नहीं है या इसके साथ कुछ और भी करें)।

इस कोड:

vector<double*> vop = new vector<double> (3); 
vop.push_back(*new_mv_pt); 
cout << (*vop)[1] << endl; 

क्योंकि vop काम नहीं करता double* रों का एक वेक्टर है, और आप इसे में एक vector<double> सम्मिलित करने के लिए कोशिश कर रहे हैं। सही दृष्टिकोण के लिए Ben's answer देखें।

7

वाह, धीमा हो गया!

आप अपनी याददाश्त के साथ कुछ सुंदर पागल चीजें कर रहे हैं, तो चलिए शुरुआत से शुरू करते हैं।

आपके पास एक एकल वेक्टर है जिसमें इसमें 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 

और वहाँ तुम जाओ, जो कुछ टिप्पणी की बाहर कोड को हटा दें और अचानक, अपना सामान एक सीटी के रूप में साफ है!

बेशक, अब, अंतिम सवाल मैं तुम्हारे लिए है: क्या हो आपको लगता है कि कर रहे हैं वैक्टर की संकेत के संदर्भ की ओर इशारा करने के लिए इन सभी संकेत की आवश्यकता है?

+0

यह बेहद सहायक था। तुमने मुझे बहुत सोचा। आपका बहुत बहुत धन्यवाद। –

+0

यह एक बहुत ही सरल सवाल का एक अविश्वसनीय रूप से विस्तृत उत्तर है। आप सर समर्थक हैं! +1 –