Stack und Heap Erzeugung

Hallo!

Wenn ich mich nicht irre wird die Unterscheidung zwischen Erzeugung auf Heap und Stack folgendermaßen vorgenommen:


void test()
{
// auf den Stack
MyClass obj;
// auf dem Heap
MyClass *obj = new MyClass();
}

So weit, so gut: Die Stack-Erstellung bedeutet ja, dass obj an den scope der Methode test() und somit an deren Stack gebunden wird.

Doch was passiert in diesem Fall

class MyClass2
{
public:
MyClass obj;
}

Das entspricht ja der Notation für die Erzeugung auf dem Stack. Aber wo landet das Objekt letztendlich? Auf einem Stack kann ja nicht sein, da es nicht an den scope irgendeiner MEthode gebunden ist …

Hallo,

Wenn ich mich nicht irre wird die Unterscheidung zwischen
Erzeugung auf Heap und Stack folgendermaßen vorgenommen:

> void test()  
> {  
> // auf den Stack  
> MyClass obj;  
> // auf dem Heap  
> MyClass \*obj = new MyClass();  
> }

Soweit richtig.

So weit, so gut: Die Stack-Erstellung bedeutet ja, dass obj an
den scope der Methode test() und somit an deren Stack gebunden
wird.

Mit Scope meint man üblicherweise die Sichtbarkeit der Variable im Quelltext. Die Unterscheidung Stack/Heap findet aber auf der Speicherebene statt.
Wobei es stimmt, dass das Objekt auf dem Stack zu existieren aufhört, wenn die Funktion verlassen wird.

Doch was passiert in diesem Fall

class MyClass2
{
public:
MyClass obj;
}

Das entspricht ja der Notation für die Erzeugung auf dem
Stack.

Nein, das ist Vererbung, und dabei wird kein Objekt erzeugt. Wenn du dann eine Instanz erzeugst, enthält die obj dort, wo das Objekt auch liegt. Wenn du mit new() eine Instanz von MyClass2 erzeugst, wird obj auch auf dem Heap liegen, wenn du eine Instanz auf dem Stack erzeugst, wird auch obj auf dem Stack liegen.

P.S. Bitte verwende

-Tags um deinen Code, damit die Einrückungen erhalten bleiben.

Grüße,
Moritz

Hallo!

Wenn ich mich nicht irre wird die Unterscheidung zwischen
Erzeugung auf Heap und Stack folgendermaßen vorgenommen:

Hallo,

du solltest dir darüber klar sein, dass das alles nur Konventionen sind oder auch nur Eigenschaften eines bestimmten Compilers.

1: Delphi legt alle Objekte auf dem heap an, das, was unter der Adresse des Objekts steht ist nur ein Zeiger. Im wesentlichen kümmert sich darum die Speicherverwaltung des Systems (des Delphi-Systems!).

2: In allen Sprachen für PCs werden lokale Variablen auf dem Stack gespeichert (wie du vermutest), bei embedded Systemen ist das aber häufig anders, weil dort kein grosser Stack zur Verfügung steht: C8051 verwendet normale Speicheregister, die wenn möglich mehrfach verwendet werden (so was wie „global but reusable“).

3: Ältestes Beispiel: MBasic verwaltet Strings ganz extra (nach jeder Operation neuer Speicherplatz) und macht gelegentlich eine Garbage Collection.

Deine Fragen sind daher nur aus dem Handbuch des aktuellen Compilers zu beantworten.

Gruss Reinhard

Nein, das ist Vererbung, und dabei wird kein Objekt erzeugt.
Wenn du dann eine Instanz erzeugst, enthält die obj dort, wo
das Objekt auch liegt. Wenn du mit new() eine Instanz von
MyClass2 erzeugst, wird obj auch auf dem Heap liegen, wenn du
eine Instanz auf dem Stack erzeugst, wird auch obj auf dem
Stack liegen.

Da verstehe ich Deine Antwort nicht. Wo siehst Du hier eine Form der Vererbung?

Hallo,

Sorry, ich hab unfug geschrieben.
Ich hatte

MyClass2: public MyClass { .. };

gelesen ;-(

Grüße,
Moritz

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo,

du solltest dir darüber klar sein, dass das alles nur
Konventionen sind oder auch nur Eigenschaften eines bestimmten
Compilers.

Meistens sind es Eigenschaften der Programmiersprache, nicht des Compilers.

Und bei C/C++ darf jeder Compiler lokale Variablen auf dem Stack anlegen, d.h. es ist immer ein Programmierfehler, einen Pointer auf eine lokale Variable zurückzugeben.

Grüße,
Moritz

Hallo

Wenn ich mich nicht irre wird die Unterscheidung zwischen
Erzeugung auf Heap und Stack folgendermaßen vorgenommen:
void test()
{
// auf den Stack
MyClass obj;
// auf dem Heap
MyClass *obj = new MyClass();
}

So weit klar …

So weit, so gut: Die Stack-Erstellung bedeutet ja, dass obj an
den scope der Methode test() und somit an deren Stack gebunden
wird.

‚Run time scope‘!

Doch was passiert in diesem Fall
class MyClass2
{ public:
MyClass obj;
}

Nichts. Das ist eine Deklaration und keine
Instantiierung (siehe Moritz).

Das entspricht ja der Notation für die Erzeugung auf dem
Stack. Aber wo landet das Objekt letztendlich? Auf einem Stack
kann ja nicht sein, da es nicht an den scope irgendeiner
Methode gebunden ist …

Obige Deklaration tut nichts ausser zu deklarieren,
wie das Objekt mal aussehen soll, wenn es instantiiert
(als Variable zum Leben erweckt) wird.

Die Deklaration:

 class MyClass2 { 
 public:
 MyClass obj;
 };

„deklariert“ ein ‚compound-Objekt‘ (enthält eine
weitere nichttriviale Datenstruktur als Member). Jetzt
kann MyClass bei der Instantiierung an sich intern eine
„Heap allocation“ im Konstruktor machen oder nicht.
Das ist ja nicht ersichtlich.

Selbst wenn die umhüllende Klasse MyClass2 in einem
Block { … } ohne „new“ instantiiert wird (also
auf dem Stack), wird die enthaltene Klasse MyClass
ihre Allokationen trotzdem auf dem Heap durchführen.

Wird MyClass2 per „new“ instantiiert, hat man am Ende
faktisch zwei getrennte Speicherbereiche, den einen
für die umgebende Klasse mit allen nichtdynamisch-
alloziierenden Membern beider Klassen und einen
Speicherbereich aus der Alloziierung der enthaltenen
Klasse.

Grüße

CMБ

Ersteinmal vielen Dank für die vielen Antworten, langsam kommt Licht in die Sache. Allerdings möchte ich auf Folgendes nochmal eingehen:

Doch was passiert in diesem Fall
class MyClass2
{ public:
MyClass obj;
}

Nichts. Das ist eine Deklaration und keine
Instantiierung (siehe Moritz).

Ich habe mein MS VC 2003 Compiler grade nicht griffbereit, aber ich meine, das Objekt obj tatsächlich benutzt zu haben. Es hat von mir eine Dummyvariable x bekommen, welche im Konstruktor auf 10 initialisiert wurde. Diese Variable war im Konstruktor von MyClass2 sofort ansprechbar, was bedeuten würde, dass der Compiler „MyClass obj“ bereits als Definition sieht, wie es auch im lokalen Kontext ist.
Wäre „obj“ nicht definiert, sondern nur deklariert, dann wäre meine Frage ja gegenstandslos …