A
HugoW schrieb:
-
b) Der Ausdruck Kopieren ist hier verkehrt. Du führst eine Zuweisung durch, da center an der Stelle bereits existiert. Über die Initialisierungsliste würdest du tatsächlich Kopieren, nicht Zuweisen (Zuweisungsoperator vs. Kopierkonstruktor).
Hmmm....ich dachte bei einer Zuweisung wird der "Inhalt" des Objekts rechts des "=" in den Speicherplatz des Objekts links kopiert? Nein? Wie darf ich mir eine Zuweisung dann speichertechnisch vorstellen?
Das problem ist einfach das es zwei Formen gibt (Kopie und Zuweisung) die man sprachlich irgendwie auseinander halten sollte. Eine Kopie wird durch Aufruf des Kopierkonstruktors erledigt, man erstellt dabei ein neues Objekt mit als Kopie des ersten. Bei einer Zuweisung existiert das Zielobjekt bereits, und jeder Wert wird einzeln zugewiesen - Du kannst es zwar kopieren nennen, aber dann kommt man hier ein wenig in Namenskonflikt.
Und bestimmte Sachen kann man nicht zuweisen, sondern nur Kopieren (Referenzen, Konstanten...).
HugoW schrieb:
@ zu
static void Cross3(Vec3f &c, const Vec3f &v1, const Vec3f &v2);
Okay, man übergibt also eine Referenz, wenn ich das richtig verstanden habe, ist das jedoch eine Adresse.
Vergiß hier einfach mal Zeiger. Referenzen mögen intern als Zeiger abgebildet werden (können unter Umständen aber vom Compiler gänzlich wegoptimiert werden), sind aber von der Behandlung etwas anderes. Unter C gab es nur die Zeiger, und dort hat sich Referenz in dem Zusammenhang im Sprachgebrauch etabliert. In C++ gibt es im wesentlichen drei Übergabeformen:
int foo1(int a); // [1] Als Kopie (C, C++)
int foo2(int & a); // [2] Als Referenz (C++)
int foo3(int * a); // [3] Als Zeiger (C, C++)
1. Hier wird eine Kopie angelegt und man arbeitet innerhalb der Funktion mit der Kopie.
1.1 Diese Übergabeform ist für integrale Datentypen (int, float...) die Übliche.
2. Übergabe als Referenz. Wie sie intern abgebildet wird (ob nun wegoptimiert oder als Zeiger) vergiss hier einfach mal. Eine Referenz lässt sich wie die Originalvariable verwenden, sie IST (aus Programmierersicht) die Originalvariable.
2.1 Diese Übergabeform sollte man verwenden, wenn man den Originalwert manipulieren will.
2.2 Eine konstante Referenz sollte man der Übergabe als Kopie vorziehen, wenn man Objekte von Klassen/Strukturen übergeben will.
2.3 Referenzen können keine temporären Variablen zugeordnet werden, Konstanten Referenzen schon (siehe Beispiel unten)
3. Übergabe als Zeiger. Ein Zeiger ist eine Adresse im Speicher und man muss ihn dereferenzieren um an das eigentliche Objekt zu gelangen. Zudem kann ein Zeiger die Adresse NULL (0) annehmen, um anzudeuten das kein Objekt übergeben wurde. Dies muss man auch bei der Programmierung berücksichtigen.
3.1 Zeiger würde ich immer dann wählen, wenn ein Objekt nur optional ist.
Ein großes Problem das du hast, ist die Syntax. Bei einer Referenzübergabe gibst du niemals eine Adresse an, sondern rufst sie wie bei einer "normalen" Funktion auf. Nur Zeiger benötigen Adressen, und leider wird hier (dank C-Herkunft das & Symbol als Adressoperator verwendet - Dies hat aber nichts mit einer Referenz zu tun):
int foo1(int a); // [1] Als Kopie (C, C++)
int foo2(int & a); // [2] Als Referenz (C++)
int foo3(int * a); // [3] Als Zeiger (C, C++)
int main()
{
int zahl = 0;
foo1(zahl); // \ Hier unterscheiden sich vom Aufruf weder die
foo2(zahl); // / Übergabe als Kopie, noch als Referenz.
foo1(3); // Die Übergabe eines temporären Wertes geht aber
// Fehler: foo2(3) nicht mit (nicht-konstanten) Referenzen
// Zeiger sind was ganz anderes...
foo3(&zahl); // Hier dient "&" als Adressoperator
}