Autokiller677 schrieb:
Das fängt (meiner Erfahrung nach) schon bei so simplen Sachen wie Manipulationen von Strings an, weil viele, die eben direkt z.B. Python gelernt haben, nie mit char* arrays, Listen von Arrays etc. rumgehampelt haben und daher nicht wissen, dass das im Hintergrund schon eher aufwändig ist, wenn man massiv mit strings durch die Gegend schmeißt und schnipselt.
Ich habe im vorherigen Post noch überlegt, ob ich Strings als Gegenbeispiel anführen soll. Wenn du direkt Java lernst (nur als Beispiel, man könnte auch andere Sprachen heranführen), dann weißt du, dass Java-Strings immer immutable sind und jede Änderung an einem String ein neues Objekt erzeugt, was eben teuer ist. Das steht so in jedem brauchbaren Buch, spätestens dann, wenn der StringBuilder erörtert wird (was er in jedem Buch wird). Des Weiteren sind Strings hier Referenztypen, das heißt, dass sie irgendwo im Heap stehen und meine Variable nur als "Zeiger" fungiert - weise ich ihr einen neuen String zu, dann wird der alte String nicht überschrieben, die Variable zeigt jetzt plötzlich nur an eine andere Stelle im Heap auf ein neues String-Objekt*. Und so weiter und so fort. Ich wüsste hier überhaupt nicht, wie mich Vorwissen in C/++ mit meinem Verständnis für Strings in Java schneller ans Ziel bringen würde als es einfach direkt zu lernen.
* so funktioniert btw. quasi alles in Python, evt. rührt deine Verwirrung bzgl. Parameter daher.
Autokiller677 schrieb:
(BTW - wie würde ich in Python eine verkettete Liste selber implementieren? Ohne Pointer / Referenzen stehe ich da gerade etwas im Regen).
Ich denke erneut, dass dich hier C/++ eher verwirrt. Es geht wieder um den Begriff Referenz in Python, Java, C# etc., der in C++ eher einem Pointer entsprechen würde als einer Referenz (siehe hierzu aber ganz unten).
Du hättest jedenfalls eine Art Container-Klasse (bestenfalls generisch), deren Instanz a) genau ein Element des generischen Typs aufnimmt und b) über eine Referenz auf den nächsten Container verweiset, der wiederum ein Element hat und auf den nächsten Container verweist usw. Das ganze wäre in einem eigenen Typ gekapselt, der Methoden bereitstellt, mit denen man neue Elemente hinzufügen kann (aka an den letzten Container der Liste per Referenz einen neuen Container dranhängen und das einzufügende Element im neuen Container ablegen). Eine andere Operation könnte das x-te Element auslesen, in dem sie x mal von Container zu Container springt und beim Zielcontainer das Element herauszieht.
Die vorgefertigten Collections dieser Sprachen sind aber i.d.R. nativ implementiert.
Autokiller677 schrieb:
Hast du einen guten Link, der das Konzept einfach und verständlich erklärt? Ich habe in gut 2 Jahren Python sowas nicht gefunden und stehe daher in Rand- / Ausnahmefällen meistens doch mit Try-and-Error da, weil ich es eben absolut nicht Schema-F empfinde was da abgeht. Letztlich lassen sich die Probleme dann meistens darauf zurückführen, dass eben im Code nicht direkt klar ersichtlich ist, was jetzt Referenz und was Objekt ist und man daher mal wieder im falschen Scope rumgeändert hat.
Du hast quasi immer Referenzen (nämlich deine ganz normalen Variablen) auf Objekte, die irgendwo im Heap rumliegen. Übergibst du jetzt ein Objekt an eine Funktion/Methode, dann übergibst du eigentlich nicht das Objekt selbst, sondern die Referenz auf das Objekt - diese Referenz wird bei diesem Vorgang auch noch kopiert. Auch wenn die Referenz jetzt im Body der Methode eine andere ist wie die außerhalb (wie gesagt, wurde kopiert), so zeigen dennoch beide Referenzen auf das selbe Objekt. Änderst du in der Methode jetzt etwas am Objekt über die Referenz in der Methode, so sind diese Änderungen auch über die Referenz außerhalb der Methode sichtbar, denn beide zeigen ja auf das selbe Objekt. Du kannst jedoch NICHT die äußere Referenz selbst ändern, indem du beispielsweise der Referenz in der Methode etwas neues zuweist. Das würde nur dazu führen, dass die Referenz in der Methode auf etwas neues zeigt, die Referenz außerhalb jedoch nach wie vor auf das alte Objekt.
Das ist quasi erstmal die ganze Geschichte. Jetzt kann es sein, dass das übergebene Objekt (bzw. das Objekt hinter der übergebenen Referenz) Immutable ist. Das heißt, du kannst das Objekt gar nicht verändern. Und wenn du es in der Methode nicht verändern kannst, dann sind auch keine Änderungen über die Referenz außerhalb der Methode sichtbar. Das ist aber kein anderer Fall der Übergabe, sondern nur eine Eigenschaft des übergebenen Datentyps.