Grundlegende Frage zur Übergabe bei Objekten



  • So, ich bin es mal wieder um habe nun eine größere Frage.
    In den Büchern die ich habe konnte mir diesbezüglich nicht weitergeholfen werden, da die Beispiele einfach zu "einfach" sind.

    Also erst einmal folgende Situation (einige kennen meine Probleme bereits).
    Ich implementiere einen Algorithmus bestehend aus mehreren Klassen.
    Während der Algorithmus abläuft können Objekte namens Node erzeugt und gelöscht werden.

    1. Wenn ich Objekte von Node während der Laufzeit anlege, muss ich diese dann mit

    Node actualNode = new Node();
    

    erzeugen?
    oder kann ich einfach

    Node actualNode;
    

    schreiben?

    Also mein Problem ist, ich verstehe nicht ganz, wann ich auf Objekte noch zuggreifen kann bzw. wann die "verschwinden"!?

    2. Wenn ich ein solches Objekt besitze, welches mehrere Typen von int, double oder vector enthält.
    Wie gebe ich diese zurück. Also kann ich einfach Referenzen darauf zurückgeben?
    Müssen diese Typen innerhalb des Objekts besonders angelegt werden? Oder muss ich Pointer darauf zurückgeben? Wieso bräuchte ich dann Pointer darauf, warum geht nicht alleine eine Referenz?



  • redbomber schrieb:

    1. Wenn ich Objekte von Node während der Laufzeit anlege, muss ich diese dann mit

    Node actualNode = new Node();
    

    erzeugen?
    oder kann ich einfach

    Node actualNode;
    

    schreiben?

    Das erstere geht nicht, es muss heißen:

    // Heap
    Node * pointee = new Node(); // Allokieren von Speicher auf dem Heap,
                                 // zugriff über die Speicheradresse
    // ...
    delete pointee;              // Später wieder freigeben!
    
    // Stack
    Node actualNode;             // Anlegen auf den Stack, Zugriff über Objekt
    

    redbomber schrieb:

    Also mein Problem ist, ich verstehe nicht ganz, wann ich auf Objekte noch zuggreifen kann bzw. wann die "verschwinden"!?

    Ein Objekt lebt solange, wie es im "Scope" bleibt:

    // 1. Objekte auf dem Heap
    int main()
    {
        int a;
        {
            int b;
            // hier ist a und b gültig
        }   // <-- b wird ungültig
    }   // <-- a wird ungültig
    

    Bei Objekten auf dem Stack sieht es ein wenig anders aus. Solche Objekte verwaltet man über den Zeiger. Dieser verliert auch seine Gültigkeit wie oben, es erfolgt aber keine automatische Freigabe des Objektes auf den er verweist. Dies muss man selbst mit delete durchführen.

    Hierzu und zu allen anderen solltest du aber in ein C++ Buch deines Vertrauens schauen.

    redbomber schrieb:

    2. Wenn ich ein solches Objekt besitze, welches mehrere Typen von int, double oder vector enthält.
    Wie gebe ich diese zurück. Also kann ich einfach Referenzen darauf zurückgeben?

    Grundsätzlich: Lokale Variablen kannst du nicht als Referenz zurückliefern, sondern nur als Kopie:

    int& foo_falsch()
    {
        int i;
        return i;
    }  // i geht aus dem Scope, ist daher ungültig, und es ist undefiniert was
       // ankommt.
    
    int foo_richtig()
    {
        int i;
        return i;
    }  // i geht aus dem Scope, aber der Rückgabewert ist eine Kopie von i
    

    Referenzen kannst du nur zurückgeben, wenn die Variable die Rückgabe überlebt:

    class A
    {
      private:
        int i;
      public:
        int& foo()
        {
          return i; // <-- Dies ist wiederum möglich, da der Member solange lebt,
                    //     wie die Instanz. Normalerweise gibt man aber keine
                    //     nicht-konstanten Referenzen auf Member zurück
        }
    };
    

    redbomber schrieb:

    Müssen diese Typen innerhalb des Objekts besonders angelegt werden? Oder muss ich Pointer darauf zurückgeben? Wieso bräuchte ich dann Pointer darauf, warum geht nicht alleine eine Referenz?

    Innerhalb eines Objektes müssen Elemente (Membervariablen) nicht speziell angelegt werden, initialisieren sollte man diese aber in der Initialisierungsliste des Konstruktors:

    class A
    {
      private:
        int i;
        int j;
      public:
        A()
        : i(4), // \ Initialisieren der Membervariablen
          j(5)  // /
        {
          i = 6; // Dies ist eine Zuweisung, keine Initialisierung!
        }
    };
    

    Konstanten und Referenzen als Member kann man nur in der Initialisierungsliste setzen, niemals nachträglich.

    cu André
    P.S: Was du auch noch lernen solltest wäre vermutlich "Call-By-Value", "Call-By-Reference"... aber dazu lasse ich dich erstmal die Forensuche bemühen.



  • Zu Zeigern und dynamischem Speicher sollte man noch sagen, dass der allokierte dynamische Speicher immer so lange allokiert bleibt, wie Du es möchtest. Soll heissen, wenn Du ein Objekt, welches Du mit new allokierst nicht explizit mit delete wieder freigibst, bleibt es bestehen, bis das Betriebsystem den Speicher wieder freigibt, so es das denn kann.



  • deshalb sollte mann auch auf smartpointer zurück greifen vorallem die aus boost bieten sich dafür sehrgut an
    zu diesem thema gibt es hier im forum mehere beiträge


Anmelden zum Antworten