Seite 1 von 1

Frage zum C++ Scopebereich

Verfasst: 28.06.2008 19:40
von milan1612
Da die Frage wahrscheinlich echt lächerlich ist, poste ich sie mal lieber hier,
in einem C++ Fourm würden sie mich eh nur auslachen :lol:

Also:

Code: Alles auswählen

class EineKlasse {
};

EineKlasse gib()
{
  EineKlasse blubb();
  //...
  return blubb;
}

int main()
{
  EineKlasse blubb = gib()
  //...
}
Ich erstelle in der function gib() eine Instanz von EineKlasse auf dem Stack.
Wenn ich diese dann zurückgebe verliert sie ja eigentlich ihren Scope und müsste
automatisch gelöscht werden. Ist ein standard-konformer Compiler dazu in
der Lage mitzukriegen dass die Rückgabe noch verwendet wird oder löscht
der ohne Wenn und Aber wenn der Scope verlassen wird?

Danke :)

Re: Frage zum C++ Scopebereich

Verfasst: 28.06.2008 23:54
von Danilo
In diesem Falle wird eine temporäre Kopie des Objektes zurückgegeben.

Also aufpassen, wenn Du zum Beispiel Zeiger in der Klasse lagerst.
Dann wird das Objekt kopiert, das Original zerstört, und die Kopie
zurückgegeben. Der Destruktor des Originals wird also am Ende
der Funktion aufgerufen, und dieser zerstört dann die Zeiger.
Da die Kopie aber trotzdem noch die alten Zeiger benutzt, die ja
nun schon freigegeben wurden, kann es so zum Crash kommen.

Deshalb soll man auch für jede Klasse, die Zeiger/Handles verwaltet,
einen Kopiekonstruktor und einen Zuweisungsoperator explizit anlegen,
worin dann richtig kopiert und erzeugt wird.

Das ist die offizielle Vorgehensweise. Einige Compiler können das
wohl optimieren und machen nicht erst eine Kopie, aber das ist
eben nicht offiziell und kann zu ungewünschten Nebeneffekten führen.

Code: Alles auswählen

#include <iostream>

class EineKlasse {
  private: int* p;

  public: EineKlasse() {
    p = new int;
    std::cout << "Konstruktor EineKlasse" << std::endl;
  }

  public: ~EineKlasse() {
    if(p) delete p;
    std::cout << "Destruktor EineKlasse" << std::endl;
  }

  public: int getP(void) {
    return *p;
  }

  public: void setP(const int x) {
    *p = x;
  }

  public: EineKlasse(const EineKlasse &ek) {
    std::cout << "Kopie-Konstruktor EineKlasse" << std::endl;
    p = new int(*ek.p);
  }

  public: EineKlasse& operator=(const EineKlasse& ek) {
    std::cout << "Zuweisungsoperator EineKlasse" << std::endl;
    if(this!=&ek) {
      if(p) delete p;
      p = new int(*ek.p);
    }
    return *this;
  }

};


EineKlasse gib()
{
  EineKlasse blubb,b;

  blubb.setP( 1111 );
  b = blubb;           // Zuweisungsoperator =

  std::cout << "getP b: " << b.getP() << std::endl;
  
  EineKlasse y(blubb); // Kopie-Konstruktor, erzeugt aus einem Objekt ein neues

  std::cout << "getP y: " << y.getP() << std::endl;
  
  return y; // erzeugt neues temporaeres Objekt und gibt diese Kopie zurueck
} 


int main (int argc, char *argv[])
{
    EineKlasse x = gib();

    std::cout << "getP: " << x.getP() << std::endl;
    
    return(0);
}

Verfasst: 29.06.2008 00:29
von milan1612
Ahh, ich danke dir :allright:
Sehr anschauliches Beispiel, das erklärt einiges über das ich mich schon oft gewundert habe.