Stack versus Heap

Hallo!

Mich plagt sein längerem schon folgende Frage:
Wo ist der Unterschied ob ich eine Variable in C/C++ mit
Code:
int i;
oder mit
Code:
int i = new int;
deklariere?

Ersteres ist auf dem Stack und letzteres auf dem Heap. Aber im Endeffekt hab ich das selbe Ergebnis. Was heist das also für mich?
Wann deklariere ich eine Variable auf dem Stack und wann auf dem Heap?

Ich hoffe ihr könnt mir helfen. :)


Nimda05
 
Beim ersteren nutzt du eine "normale" Variable, die eben nur diese einen Wert aufnehmen kann, während du beim zweiteren die Distanz einer Klasse (also ein Objekt) erstellst, das noch eigene Funktionen hat usw.
 
Ja, aber wo ist denn da der Unterschied?
Ich könnte mit

Code:
class blub{

[...]
}

int main(void){

  blub blubbablub;
  return 0;
}

doch auch eine Instanz der Klasse erstellen. Ich mein, ich weiss zwar dass man das so nicht macht, aber warum nicht ist die Frage. ;)
 
Original von bitmuncher
Beim ersteren nutzt du eine "normale" Variable, die eben nur diese einen Wert aufnehmen kann, während du beim zweiteren die Distanz einer Klasse (also ein Objekt) erstellst, das noch eigene Funktionen hat usw.

Das ist nicht ganz richtig. Erst einmal müsste es so heißen:
Code:
int *i = new int;
Diese Möglichkeit erstellt einen Zeiger auf dem Stack und einen Int auf dem Heap. Der Zeiger verweist dann auf den Heap. Normalerweise benutzt man keine Zeiger für einfache Variablen, da das einfach nur zusätzlich Speicher und Rechenzeit braucht und weiter keinen Nutzen hat.

Interessant werden Zeiger eher für Klassen und Funktionen, da sie an verschiedenen Stellen anstelle des originalen Codes (der originalen Daten) eingesetzt werden können.
Beispielsweise könnte man eine Klasse an eine Funktion übergeben wollen. Wenn man die Variante ohne Zeiger wählt, wird eine Kopie der Klasse erstellt und diese dann an die Funktion übergeben. Die Zeiger-Variante übergibt logischerweise nur einen Zeiger.

Fazit: Zeiger nur für Datenstrukturen wie structs, classes und arrays verwenden, wenn diese an Funktionen übergeben werden sollen, alles andere ist sinnlos und macht den Code nur komplizierter. Pointer-Arithmetik ist eine Wissenschaft (und Fehlerklasse) für sich, und eins der Dinge, für die C(++) bei manchen verflucht und bei manchen geliebt wird.
 
grössere Datenstrukturen werde in der imperativen (also prozedural wie auch objektorientiert) Programmierung auf dem Heap erzeugt. In Aller Regel! Der punkt ist halt, dass du auf den Stack eine Variable legst, die bloss einen Pointer hat auf die datenstruktur im heap beim 2. beispiel, beim ersten beispiel hat die variable auf dem stack genau halt den inhalt, den du reinschreibst.

Dynamische Datenstrukturen erzeugt man in C/C++ auf dem Stack nur mit alloca, wobei ich jetzt gerade nicht weiß, wie verbreitet das ist, ich glaub aber eher nicht
 
Es stimmt nicht dass das Ganze nur für Felder oder Klassen benutzt wird, sondern auch für Listen oder ähnlichen logischen "Strukturen".
 
Ich würde aber empfehlen, wenn man Objekte/structs oder ähnliches in C++ an Funktionen übergibt, dann sollte man nicht Zeiger, sondern Referenzen verwenden. Das ist bequemer und weniger fehleranfällig und von der Performance/dem Rechenaufwand identisch mit der Zeiger-Variante.(erzeugt letztendlich den selben Maschinencode)
 
Original von Lesco
Ich würde aber empfehlen, wenn man Objekte/structs oder ähnliches in C++ an Funktionen übergibt, dann sollte man nicht Zeiger, sondern Referenzen verwenden. Das ist bequemer und weniger fehleranfällig und von der Performance/dem Rechenaufwand identisch mit der Zeiger-Variante.(erzeugt letztendlich den selben Maschinencode)

Bei Referenzen musst du jedoch aufpassen, dass diese noch auf dem Stack vorhanden ist :)
Mit anderen worten, eine Init Funktion welche eine Liste (mit Referenzen) abfüllt, wird nach der Init Funktion nur noch Müll beinhalten. Ein Zugriff auf diese ergibt ein "Segmentation Fault".
 
Referenz sollte man nur verwenden, wenn das übergebene Objekt in der Funktion nicht verändert, weil der Anwender nicht direkt merkt, dass es ne Referenz ist. Am besten im Prototyp direkt konstant deklarieren.
 
@above
Wieso das denn kann man nicht einfach folgendes machen

object& meineFunktion(object &tata)
{
//veraenderung des Objeltes
return tata;
}

dann muesste man sich nicht mit dem -> Operator auseinandersetzen und der Codewuerde im vergleich zu normalen Instanzen einheitlicher und leichter zu lesen.
mfg

sw33t
 
In dem Fall würde ich z.B einen Zeiger benutzen. Immer noch den Fall gesetzt, dass der User denkt der macht CallByValue könnte er ja denken die Variable, die er übergeben hat bleibt unverändert und rechnet nach dem Aufruf der Funktion damit weiter in dem Glauben es ist immer noch der alte Wert. Aber da hat sicher jeder seine eigenen Vorlieben,
 
Zurück
Oben