Lebensdauer von Zeigern in Methoden / Funktionen
-
<vorwort>Ich arbeite mich gerade wieder in C++ ein, also verzeiht mir, falls meine Fragen sehr einfach sind. Ich habe jede Menge Tabs offen, in denen ich die Antwort auf diese Frage nicht gefunde habe.
</vorwort>Wie lange leben Zeiger, die ich in einer Methode erstelle? Leben die wie Variablen nur innerhalb der Funktion oder muss ich sie am Ende explizit löschen? Würde foo nach Ende der Laufzeit von methode noch existieren?
void ClName::methode(char* bar) { char* foo = new char; strcpy(foo, bar); ... }
-
ja die zeiger schon, die sind wie normale lokale variablen auch nicht unbegrenzt lebend.
aber das was dahinter steht (also das in deinem fall per new angeforderte) das sieht schon anders aus.
das ding ist nämlich, wenn du per new neuen speicher anforderst musst du ihn auch selsbt wieder löschen, ansosnten lebt dieser ewig weiter(wobei ewig vom betriebsystem bei programmende terminiert wird). daher aufpassen
google mal nach memory leak, sollte in jeden 2. klassigen tutorial auch schon erklärt sein
-
kauflummi schrieb:
char* foo = new char; strcpy(foo, bar);Du allokierst 1 Zeichen und versuchst, einen String dorthin zu kopieren. Das geht natürlich schief.
In C++ gibt es std::string für Zeichenketten. Damit schreibst du das Ganze als:
#include <string> ... void ClName::methode(const std::string& bar) { std::string foo = bar;Als kostenlose Zugabe brauchst du dich dann auch nicht um den Speicher zu kümmern (Stichwort RAII).
Du solltest (gerade als C++-Anfänger) strcpy und C-Strings meiden!
-
kauflummi schrieb:
Wie lange leben Zeiger, die ich in einer Methode erstelle? Leben die wie Variablen nur innerhalb der Funktion oder muss ich sie am Ende explizit löschen? Würde foo nach Ende der Laufzeit von methode noch existieren?
Zeiger sind ganz normale Variablen. die Regeln für die Gültigkeit bzw. Sichtbarkeit von Variablen, gelten auch für Zeiger.
Was anders gilt nur für dynamisch alozierten Speicher (new, malloc etc.). Deren Gültigkeit ist auf die Laufzeit des Programmes beschränkt bzw. bis sie explizit wieder freigegeben (delete, free etc.) wurden. Je nach dem, was früher eintritt.
Um dynamisch angeforderten Speicher vernünftig verwalten zu können, brauchst Du also mindestens einen gültigen Zeiger, der darauf verweist. Wenn Du diesen in die ewigen Jagdgründe schickst, bevor du den Speicher freigegeben hast, ist der Speicher "verloren" bis die Anwendung beendet wird.
Achtung: Nachdem der Speicher freigeben wurde, dürfen alle Zeiger, die darauf evt. noch verweisen nicht mehr verwendet werden, ehe ihnen nicht eine neue, gültige Adresse zugewiesen wurde.
Ich hoffe ich habe mich klar genug ausgedrückt.
mfg Martin
-
mgaeckler schrieb:
Achtung: Nachdem der Speicher freigeben wurde, dürfen alle Zeiger, die darauf evt. noch verweisen nicht mehr verwendet werden, ehe ihnen nicht eine neue, gültige Adresse zugewiesen wurde.
Man darf sie nur nicht dereferenzieren.
-
Ah, danke. Ich hatte bei mir den Fehler gemacht, eine flache Kopie zu machen und dann zu löschen, das ist mir dann aus mehreren Gründen um die Ohren geflogen.
char* a = new char; char* b = new char; a = b; delete a;
-
314159265358979 schrieb:
mgaeckler schrieb:
Achtung: Nachdem der Speicher freigeben wurde, dürfen alle Zeiger, die darauf evt. noch verweisen nicht mehr verwendet werden, ehe ihnen nicht eine neue, gültige Adresse zugewiesen wurde.
Man darf sie nur nicht dereferenzieren.
Stimmt, so ist es besser ausgedrückt. Danke für die Verbesserung.

-
@kauflummi
Und noch als kleiner Zusatz: Du brauchst in C++ als Anfänger eigentlich nie Zeiger. Also wirklich nie. Und falls du es doch irgendwann mal brauchen solltest, stehen immer noch so genannte "Smart-Pointer" im Raum. (shared_ptr und unique_ptr) Die solltest du dir mal angucken.
-
314159265358979 schrieb:
mgaeckler schrieb:
Achtung: Nachdem der Speicher freigeben wurde, dürfen alle Zeiger, die darauf evt. noch verweisen nicht mehr verwendet werden, ehe ihnen nicht eine neue, gültige Adresse zugewiesen wurde.
Man darf sie nur nicht dereferenzieren.
Nein.
-
Nette Begründung. Ohne Zitat aus dem Standard geht hier mal grundsätzlich gar nichts, besonders bei dir.
-
314159265358979 schrieb:
Nette Begründung. Ohne Zitat aus dem Standard geht hier mal grundsätzlich gar nichts, besonders bei dir.
Genau. Also wo ist deine Begründung?
-
Ich muss hier gar nichts begründen.
-
Vor den restlichen Flames bitte "verwenden" definieren. :xmas1:
-
cooky451 schrieb:
Vor den restlichen Flames bitte "verwenden" definieren. :xmas1:
Das hat doch schon 314159265358979 für mich getan. Bevor hier weiter wegen nix gestitten wird, sollte die ganze Diskussion gelesen werden. Das ist hier doch kein Kindergarten.
mfg Martin
-
3.7.3.2§4 (C++98) gibt camper recht.
edit: Davon abgesehen müssen natürlich weder camper noch pi irgendwas begründen, allerdings aus stark unterschiedlichen Gründen.
-
Wow. Ich dachte, dass es in technischen Foren anders zugeht.
Zu meinem Beispiel: Ich erstelle aus einer Datei pro Zeile eine Instanz, auf die ich in einem Vektor Zeiger speichere. Ich wüsste nicht, wie ich das anders machen sollte.
class Team { public: [...] void initTeam(Team*, char*); void addPlayer(Player*); [...] private: [...] vector<Player*> players; }; [...] void Team::initTeam(Team* team, char* filename) { ifstream input(filename); // Open for reading string text; while(getline(input, text)) { int size = text.length(); [...] text parsen Player *addAPlayer = new Player(charname, pass, tackle, schuss); team->addPlayer(addAPlayer);
-
Kannst du "Player" denn aus irgendeinem Grund weder kopieren noch moven? Nutzt du Polymorphie? Ansonsten:
std::vector<Player> players; Player my_new_player(...); players.push_back(my_new_player); // Alternativ auch mit std::move, aber das ist wahrscheinlich erst mal egal für dich.kauflummi schrieb:
Wow. Ich dachte, dass es in technischen Foren anders zugeht.
Das sind die Allerschlimmsten. :xmas1:
PS:
C-Strings übergibt man als "const char*", damit garantiert man, dass der String nicht geändert wird. Ansonsten ist es in C++ schöner einen "const std::string&" zu verwenden, wenn man keinen besonderen Grund für C-Strings hat.Eine Methode "init" lässt schon schlechtes Design vermuten. Warum kannst du das, was du da machst, nicht im Konstruktor erledigen?
-
Danke für die Tipps, habe mal zwei Semester C++ gehört aber nicht mitgearbeitet. Du bringst wahrscheinlich die ganzen Sachen zur Sprache die ich damals nicht verstanden habe, jetzt aber für die offene Hausarbeit brauche.