Whoa, langsamer dort!
Sie machen einige ziemlich verrückte Dinge mit Ihrem Gedächtnis, also fangen wir von vorne an.
Sie haben einen einzelnen Vektor, der drei Elemente enthält. Sie möchten diesen Vektor mit einem Zeiger referenzieren. Mal sehen, wie das aussieht:
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;
Das kümmert sich um das erste Bit. Nun, lasst uns etwas tiefer hineingehen. Sie möchten einen Vektor von Referenzen auf Vektoren speichern. Okay, das klingt fair. Es gibt ein paar Möglichkeiten.Gehen wir zurück auf das Beispiel von mv
und andere Dinge:
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.
An dieser Stelle im Code, haben Sie vop
mit .at()
oder operator[]
auf den Zugang zu einem vector<double>*
zu bekommen, dann Sie dereferenzieren mit *
oder Verwendung ->
direkt daran arbeiten:
std::vector<double>* ptr_to_vector = vop[0]; // Got my pointer
std::cout << ptr_to_vector->at(0) << std::endl; // Prints '233'
diese 233 druckt, weil alle diese Sie mv
Referenzierung wird. In einem Kommentar in einer anderen Antwort sagten Sie, dass Sie eine Assertion erhalten, wenn Sie diese Zeiger löschen. Das soll passieren, weil du Dinge zweimal löschst!
Denken Sie daran, mv
, dass Sie vor langer Zeit deklariert? Nun, du hast es nicht zu einem dynamischen Vektor gemacht. Du hast es nicht new
it, und es ist kein Zeiger. Wenn die Funktion beendet wird, wird sie automatisch gelöscht - sie ruft ihren Destruktor und Chip auf dem Stapel. Wenn Sie sich ptr_to_vector
oder ptr_to_mv
ansehen, beziehen sich alle auf mv
, die sich selbst reinigt.
Wenn Sie delete aufrufen, versuchen Sie, delete auf mv
(das ist, was Sie zeigen) aufrufen und Sie sind doppelt löschen!
Also, wenn Sie einen Zeiger auf mv
haben, löschen Sie es nicht. Es ist eine stack-basierte Variable. Es wird sich selbst reinigen.
Noch folgen? Große, lassen Sie uns in sie ein bisschen mehr bekommen:
Nun, wenn es ein Grund Sie einen Vektor new
up benötigen, können Sie nicht zuordnen es mit einem alten Zeiger außer Kraft setzen (wie ich schon sagte, du wirst Speicher hinterlassen). Sie machen einen völlig neuen, frischen Zeiger:
// 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!
Die oben zeigt das Problem: Wir haben zwei Zeiger, sowohl innerhalb als vop
, wo man löschen, indem Aufruf gereinigt werden muss, und ein anderes, das nicht den Fall ist, weil es nur ein Verweis auf mv
, die automatisch reinigt! Wenn Sie über den Vektor streichen und alles löschen, wird diese böse Behauptung ausgelöst. Wie gehen wir damit um und bekommen trotzdem das Saubermachen, das wir brauchen?
Dirty und Quick Solution 1 ist nur delete vop[1]
/fresh_ptr
und damit fertig sein. Die bessere Lösung ist, dass, wenn Sie eine Ressource auf new
up, Sie es in diesem wunderbaren Ding namens std::unique_ptr
einpacken. Der Code wird wie folgt aussehen:
// 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
Und los geht, entfernen Sie alle, dass kommentierte-out-Code und plötzlich, Ihr Material ist picobello sauber!
Natürlich, jetzt die letzte Frage habe ich für Sie ist: Was zum Teufel machst du das verlangt, dass alle diese Zeiger auf Zeiger auf Referenzen von Zeigern von Vektoren?
Zuerst erhalten Sie Ihre Antwort. Zweitens, erkenne, dass dies eine schreckliche Idee ist, weil du die Fähigkeit des Vektors eliminierst, das Gedächtnis für dich zu verwalten, was (zumindest) der halbe Punkt ist, es überhaupt zu benutzen. –
Ich versuche nur herauszufinden, warum er überhaupt einen Zeiger auf einen Vektor hat. Es macht keinen konzeptionellen Sinn, es so zu tun, besonders wenn es in derselben Funktion/Klasse ist. –