Default Ctor ausreichend bei arrays/Zeigern?



  • Hallo,

    folgender Code:

    struct foo {
       char p[30];
       foo() {
          strcpy(p, "hallo");
       }	
    };
    
    class clas {
    public:
       foo myFoo;
       foo method() { return myFoo; }	
    };
    

    Wenn ich method() aufrufe, wird denke ich ja mal der Default Ctor von foo aufgerufen, der Elementweise kopiert. Bei ints usw funktioniert das natürlich, aber klappt das auch bei Arrays wie hier p?



  • Warum probierst du's nicht einfach aus?



  • Habe ich, aber ich verstehe das Ergebnis nicht.
    Wenn ich das mache:

    clas c;
    
    foo f = c.method();
    

    dann steht in c.myFoo.p und f.p "hallo", aber sie zeigen auf unterschiedliche Adressen. Das raff ich absolut nicht.



  • p ist ein Array, kein Zeiger, daher zeigt p nicht auf irgendwas. Daraus folgt, den Standardregeln von C++ folgend, dass jede Instanz von foo sein eigenes Array hat, welches auch durch die Default-Copy-Operationen ordentlich kopiert wird.



  • klammeraffe schrieb:

    Habe ich, aber ich verstehe das Ergebnis nicht.
    Wenn ich das mache:

    clas c;
    
    foo f = c.method();
    

    dann steht in c.myFoo.p und f.p "hallo", aber sie zeigen auf unterschiedliche Adressen. Das raff ich absolut nicht.

    Das überrascht doch wohl nicht wirklich bei

    klammeraffe schrieb:

    foo method() { return myFoo; }
    

    oder ?

    Ist doch so wie überall: Rückgabe per Kopie !
    Und wenn ich ein Array kopiere, bekomme ich ein anderes Array mit denselben Werten (erstmal).... das natürlich auch woanders im Speicher liegt.

    Erst Recht HIER, wo es sich ja nicht einmal um eine Zuweisung, sondern eine Initialisierung des neuen foo-Objekts f handelt (das natürlich da liegt, wo der COmpiler es eben gerade hinlegt)....

    Gruß,

    Simon2.



  • Wie stellt man sich dann am besten den vom Compiler erstellten Default CopyCtor vor?
    Ich dachte immer er sieht so aus:

    foo(const foo& f) {
       a = f.a;
       b = f.b;  // usw
       // p ist pointer, arr ist array
       // aber wie muss ich mir das bei p und arr vorstellen?
    }
    

  • Mod

    klammeraffe schrieb:

    Wie stellt man sich dann am besten den vom Compiler erstellten Default CopyCtor vor?
    Ich dachte immer er sieht so aus:

    foo(const foo& f) {
       a = f.a;
       b = f.b;  // usw
       // p ist pointer, arr ist array
       // aber wie muss ich mir das bei p und arr vorstellen?
    }
    

    Das Kopieren von Pointern ist hier kein Spezialfall, für das Kopieren von Arrays gibt es dagegen keine Möglichkeit, das exakt gleiche Verhalten explizit zu bewirken. Arrays werden elementweise kopiert:

    struct Foo
    {
        T arr[10];
        Foo(const Foo& other)
        {
            // default-copyctor sinngemäß so:
            std::uninitialized_copy(other.arr,other.arr+10,arr);
            // wenn T selbst ein array ist, müssen wir dessen Elemente kopieren und so weiter
            // (wir können nur Klassen und skalare Typen explizit kopieren)
        }
    };
    

    Diesen Vorgang müsste man in der Initialisierungsliste erledigen, und das ist syntaktisch unmöglich.



  • klammeraffe schrieb:

    Wie stellt man sich dann am besten den vom Compiler erstellten Default CopyCtor vor?
    Ich dachte immer er sieht so aus:

    foo(const foo& f) {
       a = f.a;
       b = f.b;  // usw
       // p ist pointer, arr ist array
       // aber wie muss ich mir das bei p und arr vorstellen?
    }
    

    Ja, so sieht das auch aus... und es erklärt auch deine Problematik. Der Standard-Kopierkonstruktor macht für ALLE Elemente (unabhängig davon was sie sind) eine Wertkopie, nicht desto trotz sind es eigenständige Elemente (die dann nur den gleichen Wert haben). Ein Array ist vom Verständnis her ein Element wie jedes andere (auch wenn wie camper schon geschrieben hat, eine andere Kopieform verwendet wird; Sprich der Inhalt wird kopiert, dennoch sind es unterschiedliche Arrays).

    Sofern man Pointer in einer Klasse hat wird es spannend, sofern diese auch in der Klasse angelegt und gelöscht werden. Der Wert eines Pointers ist ja schließlich die Adresse (und nur die wird kopiert), nicht der Inhalt, auf den er zeigt. Daher überschreibt man in solchen Fällen den Kopierkonstruktor um in dem Moment z.B. eine eigene Kopie des Speicherbereiches zu machen.

    cu André


Anmelden zum Antworten