Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

22.09.2015, 08:34

[C++] Zeiger auf Objekt in Vector verliert seine Daten, sobald ein neues Objekt dazukommt

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
std::vector< int > foo;         
int *foo2;

foo.push_back( 1 );
foo2 = &foo[foo.size() - 1];

foo.push_back( 2 );  // hier verliert der Zeiger seine Daten und zeigt ins nirgendwo
foo2 = &foo[foo.size() - 1];

foo.push_back( 4 );  // hier verliert er sie wieder


Ist das ein normales Verhalten, das der Zeiger immer wenn ich ein neues Objekt in den Vector schiebe seine Daten verliert und irgendwo hinzeigt? Kann mir das momentan nicht ganz vorstellen das das normal ist, dachte zuerst das es an meinen größeren Code liegt, aber als ich das obere kleine Beispiel schrieb ist der Fehler genauso aufgetreten. Ich kann den Zeiger nach dem push_back zwar immer wieder neu zuweisen, wäre aber doch sehr nervig.

CentuCore

Frischling

Beiträge: 43

Wohnort: Wien

  • Private Nachricht senden

2

22.09.2015, 08:48

Ja, dass ist "normal".
Probier mal folgendes vor deinen push_back().

C-/C++-Quelltext

1
foo.reserve(10);

Der Grund warum es jetzt geht ist, dass dein vector nicht mehr neu Speicher anfordern muss um die neuen Daten zu speichern.
Und weil im vector die Daten alle in einem riesen Block liegen (Array) werden die alten Daten einfach jedesmal neu rüberkopiert.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

3

22.09.2015, 08:50

Das ist normales Verhalten. Wenn der Vector über seine Kapazität wächst wird ein neuer Speicherbereich angefordert und der Vector zieht um. Dabei werden natürlich alle Zeiger invalidiert.

Ich weiß nicht wofür du den Zeiger brauchst, aber der Index im Vector würde es tun. Oder std::list statt vector müsste auch gehen, da dort die Elemente verteilt im Speicher liegen können und nicht umziehen müssen.

4

22.09.2015, 08:56

Naja, es ist bekanntes Verhalten.
Allerdings ist es nicht zwingend so, dass die alten Zeiger ungültig sind. Die Objekte liegen hintereinander im Speicher. Wenn du jetzt ein neues Objekt hinten an fügst aber der Speicherblock nicht mehr groß genug ist, nur dann wird verschoben. Ansonsten bleiben die alten Elemente unberührt. Das Ganze mit .reserve zu umgehen ist dann allerdings nur ein hässlicher Hack.
Allerdings ist es generell eine schlechte Idee eine Referenz/Zeiger auf ein Element in einem vector über längere Zeit zu nutzen. Nutze dafür lieber einen Index, die Zugriffszeiten bleiben dabei grundlegend die gleichen, eben weil der vector hintereinander im Speicher liegt.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

22.09.2015, 09:11

Mehrere Möglichkeiten:
1) Keine Pointer auf Elemente eines Container verwenden
2) Pointer auf Elemente eines Containers nur dann verwenden, wenn der Container nicht verändert wird
3) vector<unique_ptr<int>>
4) deque<int>
5) list<int>
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

6

22.09.2015, 09:18

Im Grunde baue ich mir eine Baumstruktur und wollte dort jetzt Zeiger auf die Objekte davor und danach legen. Die Objekte liegen bei mir dabei halt in einem Vector. Aber das ist so dann jetzt hinfällig, wenn die alle dann immer wieder ungütlig werden. Also Speichere ich jetzt dann die ganzen Index Daten. Aber gut das ich das jetzt weiß, denke werd mir jetzt aber auch mal etwas Code suchen wie man normalerweise eine Baumstruktur anlegt. Nicht das ich da ganz daneben liege.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

22.09.2015, 10:58

C++ hat übrigens auch schon Baum-Strukturen - Maps. Was genau willst Du überhaupt machen?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

8

22.09.2015, 17:33

Im Grunde benütze ich es um die Daten der Wegfindung zu Speichern. Da die KI aber wohl sehr komplex wird, muss ich sehr wahrscheinlich mehrere Pfade abspeichern und evtl. an beliebigen Punkten einspringen um nebenanliegende Felder zu überprüfen ob diese besser wären. Ich weiß zwar noch nicht ob das alles so klappt, aber bis jetzt ist es der beste Einfall den ich dazu hatte und bevor ich weiter Tagelang darüber nachgrüble probiers ich jetzt damit einfach mal.

Mehr Technisch gesagt ich will:

Mutterknoten mit beliebig vielen Kindknoten, die ihrerseits dann wieder beliebig viele Kindknoten haben. Jeder der Kindknoten soll auch seinen Mutterknoten wissen.

9

22.09.2015, 23:01

Na ja, einfach einen std::vector<std::unique_ptr<Typ>> als Member der Klasse Typ und zusätzlich noch einen Pointer Typ* auf den Elternknoten. Fertig.
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

23.09.2015, 09:31

Wenn es um eine ganz allgemeine Baumstruktur geht (beliebige, variable Anzahl an Kindern pro Knoten), dann gibt es auch noch folgende Lösungsvariante:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
class Node
{
private:
    Node* parent
    
    std::unique_ptr<Node> next_sibling;
    std::unique_ptr<Node> first_child;
public:
    Node(Node* parent)
        : parent(parent)
    {
    }
};

Jeder Knoten kennt seinen Parent und besitzt seinen nächsten Zwilling und sein erstes Kind (und damit implizit automatisch alle seine Kinder).

Werbeanzeige