Programmieren - alles kontrollieren 4.934 Themen, 20.613 Beiträge

Frage zu C++

cobra77 / 1 Antworten / Flachansicht Nickles

 ich möchte in c++ ein objekt anlegen, wie z.b.


 1) Name a("Daniela",7);
 2) Name *b = new Name("Alex",4);
 


ist es eigentlich egal ob ich ein objekt nach methode 1 oder 2 anlege und was ist der unterschied zwischen diesen beiden aufrufen.


beim zweiten aufruf wird mit new speicher alokiert. wird das beim ersten auch?


wäre nett wenn mir wer den unterschied erklären könnte. vielen dank im voraus!


mfg christoph

bei Antwort benachrichtigen
Dreamforger cobra77 „Frage zu C++“
Optionen
Grob
Ohne in die Details zu gehen, ist auf jeden Fall schon mal klar das zu jedem 'new' ein 'delete' gehört. Das heißt wenn du 'b' nicht mehr brauchst musst du es wieder freigeben. Der Zugriff auf beide funktioniert leicht unterschiedlich: auf Felder von (1) greiffst du mit '.' zu, auf die von (2) mit '->'

Feinheiten
Dann ist bei beiden noch zu beachten das sie unterschiedliche Gültigkeitsbereiche haben. Während 'a' nur in der Funktion verwendbar ist in der sie deklariert wurde und in allen von daaus aufgerufenen, kann 'b' weiter verwendet werden. Nun 'b' selbst nicht aber der Speicherbereich auf den 'b' zeigt.

Mal 3 Beispiele:

Name Fabrik1()
{ Name a("Daniela",7);
return a; }

Funktioniert perfekt. Ist aber ein wenig langsam auf Dauer da das gesamte 'Name("Daniela",7)' bei der Rückgabe kopiert wird. Also könnte man sich denken das man statt des ganzen Objekts nur eine Referenz auf das Objekt zurückgibt:

Name* Fabrik2()
{ Name a("Daniela",7);
return &a; }

Syntaktisch ist das auch ok. Leider hast du keine Garantie das es funktioniert - eher im Gegenteil: Die 'Name' Instanz ist nur innerhalb der Fabrik2() gültig, das heißt aber, dass der Pointer der Zurückgegeben wird ins Nirvana zeigt.
Wie geben wir also Pointer zurück?

Name* Fabrik3()
{ Name* b=new Name("Alex",4));
return b;}

So. 'b' selbst ist zwar selbst wieder nur innerhalb Fabrik3() gültig, aber der Speicher auf den 'b' zeigt bleibt bis zm delete verwendbar.

Technik
Warum gibt es diesen Unterschied? Du musst grundlegend zwischen 2 Verschieden Speicherbereichen unterscheiden. Zum einen gibt es den Heap zum anderen den Stack. Der Heap ist einfach ein großer Haufen Speicher von dem du dir mit 'new' Speicher holst und ihn mit 'delete' zurück gibst. Der Heap wird bei unseren 'b' Varianten verwendet.
Der Stack ist etwas umständlicher: Hier können Funktionen lokale Variablen anlegen. Stells dir wie einen Stapelpapier vor den du auf deinem Schreibtisch aufbaust. Am Anfang ist der Schreibtisch leer. Wird eine Funktion aufgerufen, so werden alle Variablen der Funktion auf ein Blatt geschrieben und das Blatt auf den Stapel gelegt. Der nächste Funktionsaufruf aus unserer Funktion heraus legt wieder ein neues Blatt auf den Stapel/Stack. Zu jedem Zeitpunkt sind Referenzen auf Blätter/Gültigkeitsbereiche die weiter unten im Stapel liegen gültig. Nur nicht nach oben. Und genau das passiert aber bei 'Fabrik2()'. Auf dem Tisch liegt das Blatt der aufrufenden Funktion, meinetwegen die 'main()'. Darin wird jetzt 'Name *geht_eh_nicht = Fabrik2();' aufgerufen, dass heißt ein neues Blatt wird auf den Stapel gelegt und die Informationen von 'a("Daniela",7)' landen da. Dann ist 'Fabrik2()' fertig und das Blatt wird wieder entfernt und weggeschmissen. Und dann steht in 'geht_eh_nicht' etwas wie "gehe ein Blatt nach oben und da steht dann die Name Instanz auf die ich zeige". Dummerweise ist das Blatt aber schon im Müll. Aus Effizienzgründen wird das Blatt zwar nicht wirklich sofort weggeschmissen, aber du kannst dich nicht mehr drauf verlassen das es noch da ist wenn du später mal drauf zugreifen willst.
bei Antwort benachrichtigen