Standardkonstruktor <-> Funktionsaufruf



  • Dieser Code ist falsch (für die Absicht, den Standardkonstruktur aufzurufen), weil er eine Funktion definiert:

    CTest test1();
    

    Dieser Code funktioniert aber:

    CTest test1 = CTest();
    

    ...warum? Es wird ein (temporäres?) Objekt CTest erzeugt und test1 zugewiesen (erfordert einen Kopierkonstruktor?) , aber eigentlich könnte hier CTest doch auch eine Funktion sein?



  • Also Koperikonstruktor brauchst du vor allem, wenn du mit Zeiger arbeitest.
    Hier nicht (unbedingt).

    Und ja CTest () könnte eine Funktion sein, aber da würde dein Compiler mekern, dass es da ein Problem mitdem Namen gibt.



  • Wenn du dir deinen Kopierkonstruktor nicht selber schreibst, dann wird eine "flache" Kopie durchgeführt. Bei einer solchen Kopie, werden die selben Adressen, welche die Zeiger (wenn vorhanden) des zu kopierenden Objekts beinhalten, an die Pointer des anderen Elements übergeben. Hierbei können z.B. Fehler auftreten, wenn der "Destruktor" von beiden Objekten aufgerufen wird, und eine Adresse gelöscht werden soll, welche schon zuvor vom anderen Objekt gelöscht wurde.
    Mit einem selbstgeschriebene Kopierkonstruktor kann man dieses Problem umgehen, in dem man eine "tiefe" Kopie erstellt. Das bedeutet, das man nicht die gleichen Adressen übergibt, sondern für die Zeiger, aus dem Objekt in das man reinkopiert, neuen Speicher reserviert, und dann nur die Werte der Zeiger, aus dem Objekt aus welchem man kopiert, übergibt.

    MfG
    Stromberg



  • anfänger93 schrieb:

    Dieser Code ist falsch (für die Absicht, den Standardkonstruktur aufzurufen), weil er eine Funktion definiert:

    CTest test1();
    

    Dieser Code funktioniert aber:

    CTest test1 = CTest();
    

    ...warum? Es wird ein (temporäres?) Objekt CTest erzeugt und test1 zugewiesen (erfordert einen Kopierkonstruktor?) , aber eigentlich könnte hier CTest doch auch eine Funktion sein?

    Fall 1: Eine Funktion wird durch die folgende Syntax gebildet:
    <typ> <funktionsname>(<parameterliste>)
    Was auch auf deinen vermeindlichen Konstruktoraufruf zutrifft. Sofern ein Objekt über einen Standardkonstruktor generiert werden soll reicht die folgende Syntax:
    <typ> <variablenname>;
    Sprich:

    CTest test1;
    

    Fall 2: Hier kann CTest auch eine Funktion sein, aber im gegensatz zu Fall 1 wird hier nicht von einer Deklaration ausgegangen. Zudem ist in dem Fall weder ein temporäres Objekt noch ein Zuweisungsoperator etc. zutreffend. Den du schreibst hier eine direkte Initialisierung...

    Das kannst du auch selber austesten:

    #include <iostream>
    
    class Test
    {
      public:
        Test() { std::cout << "Test::Test()\n"; }
        ~Test() { std::cout << "Test::~Test()\n"; }
        Test(const Test&) { std::cout << "Test::Test(const Test&)\n"; }
        Test& operator=(const Test&) { std::cout << "Test::operator=(const Test&)\n"; return *this; }
    };
    
    int main()
    {
      std::cout << "-- Abschnitt 1a --\n";
      Test a = Test(); // Direkte initialisierung (1xKonstruktoraufruf)
      std::cout << "-- Abschnitt 1b --\n";
      Test a2; // Direkte initialisierung (1xKonstruktoraufruf)
      std::cout << "-- Abschnitt 2 --\n";
      a = Test(); // 1xKonstruktor 1xZuweisungsoperator 1xDestruktor
      std::cout << "-- Abschnitt 3a --\n";
      Test b = a; // 1xKopierkonstruktor
      std::cout << "-- Abschnitt 3b --\n";
      Test b(a); // 1xKopierkonstruktor
      std::cout << "-- Ende... (Destruktoraufrufe) --\n";
    }
    

    cu André



  • Danke für eure Antworten!

    asc, ich habe deinen Code ausprobiert und weiß, dass du recht hast.

    Aber ich muss anmerken, dass in meinem Buch (C++ Primer) da etwas anderes steht:

    S. 565 der 4. Auflage

    string empty_copy = string (); // Kopierinitialisierung
    string empty_direct; //Direktinitialisierung
    [...]Die Initialisierung von empty_copy und empty_direct verwendet jeweils den string-Standardkonstruktor. Im ersten Fall legt der Standardkonstruktor ein temporäres Objekt an, das dann vom Kopierkonstruktor genutzt wird, um empty_copy zu initialisieren. Im zweiten Fall wird der Standardkonsturktor direkt auf empty_direct ausgeführt.

    Das kann ich mir also mit Rotstift rausstreichen?



  • ja. und mit C++0x wird die initialisierung dann einheitlich (hoffentlich) so aussehen:

    CTest test1 {};
    

Anmelden zum Antworten