Wozu ist das in Rust gut? Vektor umreferenzieren?



  • Nichts. Darum geht es ja gerade.
    Das Erzeugen der Kopie wäre teurer.
    Du hast aber das Gegenteil behauptet.



  • hustbaer schrieb:

    Nichts. Darum geht es ja gerade.
    Das Erzeugen der Kopie wäre teurer.
    Du hast aber das Gegenteil behauptet.

    Ich hatte kein Wort bezüglich Kopie des Vektors gesagt.
    Wenn ich sage, Vektor übergebe, dann meine ich damit ein Call by Reference. Also Übergabe des Pointers, der darauf verweist.

    In Rust wird aber, anstatt den Pointer einfach zu übergeben, ein neuer Pointer erzeugt, der dann auf die Daten zeigt.
    Und da will ich wissen, wozu das gut sein soll?
    Ich halte das für überflüssig, so nen extra Pointer zu überzeugen, für Daten, die nach verlassen der Funktion sowieso alle ungültig sind.



  • Was für ne Logik? schrieb:

    In Rust wird aber, anstatt den Pointer einfach zu übergeben, ein neuer Pointer erzeugt, der dann auf die Daten zeigt.

    Wo soll der Unterschied sein?
    Den Pointer übergeben heisst eine Kopie des Pointers zu erzeugen.
    Sonst müsste man ja einen Pointer auf den Pointer übergeben. 😕
    Und das Problem dabei wäre dann wiederrum dass man die Lebenszeit des 1. Pointers garantieren können müsste.
    Abgesehen davon dass es keinen Nutzen bringen würde, da

    1. Einen Pointer zu kopieren nicht teurer ist als einen Pointer auf den Pointer zu erzeugen und
    2. Den Pointer auf den Pointer zu dereferenzieren teurer wäre als einen einfachen Pointer zu dereferenzieren.

    Was für ne Logik? schrieb:

    Ich halte das für überflüssig, so nen extra Pointer zu überzeugen, für Daten, die nach verlassen der Funktion sowieso alle ungültig sind.

    Die machKaputt Funktion könnte genau so gut Ownership übernehmen. Dann wären die Daten nicht nach verlassen der Funktion ungültig.



  • ps:
    Ich kenne mich mit Rust nicht gut aus.
    Ich meine dass der von dir beschriebene "move" sehr billig ist -- also praktisch einfach einen Zeiger kopieren (=ein "mov" oder "push" und nicht mehr). Falls das nicht der Fall sein sollte dann bitte ich um Korrektur.



  • Warum übergibt man nicht einfach den Vektor v an die Funktion, anstatt mit großem Aufwand bei der FUnktionsübergabe einen neuen Pointer auf den Vektor zu überzeugen?

    1. es werden keine Pointer mit grossem Aufwand erzeugt- sowas gibt es gar nicht
    2. ist das Kompiletime nicht Runtime-Semantik - also 0 Performanzeinfluss

    Und wenn der Vektor kaputt gehen soll, dann hätte man ja ein Schlüsselwort einführen könnne, dass bei der Parameterübergabe dann den übergebenen Vektor auch in main kaputt macht.

    genau das beschreibt doch die Ownership-Semantik von Rust auch OHNE zusätzliches Schlüssewort nur noch weit fähiger

    Kurz: du hast noch zu wenig Ahnung von Rust - oder eher - welche Problem die Ownership-Semantik löst die du noch nicht in der normalen Entwicklung erlebt hast und daher als nicht existent "empfindest"



  • Ich verstehe nicht, was du mit pointern sagen willst. In dem ganzen Code wird kein pointer verwendet, ausser der innerhalb des vector-objects. Der ist aber irrelevant, weil man eh nicht auf ihn zugreift.





  • Was für ne Logik? schrieb:

    Ab 24:02 wird das Problem beschrieben:
    http://mirror.netcologne.de/CCC/events/hackover/2014/mp4/hackover14-6496-de-Programmiersprache_Rust_und_ihre_Sicherheitsgarantien_h264-hq.mp4

    Ich würde das nicht als "Problem" bezeichnen. Und gleich bei 26:26 wird ja auch gezeigt, wie man das in dem Fall machen sollte.

    Besitzübergabe ist trotzdem sinnvoll. Du kannst z.B. einen Vec<u8> über einen Kanal von einem Thread zu einem anderen schicken. Eine Referenz auf so einen Vektor kannst du nicht über einen Kanal verschicken, weil diese Referenz ungültig werden könnte (je nachdem, wie lange der besitzende Thread das Ding am Leben lässt).

    Edit: Habe gerade noch ein bisschen weiter geguckt (bin bei 28:40) und muss sagen, dass der Vortrag ein bisschen out-of-date ist. " int " gibt's nicht mehr, wurde umbenannt in isize . Heute würde man da "i32" oder sowas schreiben. "i32" ist auch der Default-Typ für Ganzzahlen, die nicht anderweitig deduziert werden. Und das Ausleihen würde heute so aussehen:

    show(&v[..]);
    

    Man leiht ( & ) also alle Elemente ( [..] ) aus. Es geht sogar noch kürzer:

    show(&*v);
    

    Aber das hat IMHO einen höheren "WTF?!"-Faktor.



  • Wenn Dein Englisch gut ist, kannst Du dir auch Niko's Vortrag angucken. Da geht er glaub'ich mehr drauf ein, was das geniale an (single) ownership ist. Im Prinzip macht es die Frage, ob/wann man etwas löschen oder an einen anderen Thread übergeben darf, sehr einfach. Wo die funktionalen Sprachen sich Sicherheit durch Immutibilität erkaufen, gibt Dir Rust Sicherheit, in dem "Sharing/Borrowing" kontrolliert wird.

    https://air.mozilla.org/guaranteeing-memory-safety-in-rust/

    Für die C++ Programmierer sind das keine neuen Konzepte. Aber die Implementierung ist etwas anders. Move Semantik funktioniert ein bisschen anders. Der große Unterschied zwischen C++ und Rust in dieser Hinsicht ist nur der, dass der Rust Compiler die Sache mit dem "Ausleihen" versteht und das checken kann.



  • Ich glaube, ich habe so langsam verstanden, wo das Verständnisproblem liegt. Der OP geht anscheinend davon aus, dass alle Variablen Referenzen sind, so wie das z.B. in Python der Fall ist.

    In C++ und in Rust sieht das aber anders aus. Wenn Du in Rust schreibst:

    struct Foo { x: i32 };
    
    fn main() {
        let f = Foo { x: 42 };
    }
    

    dann ist f kein Zeiger. f speichert keine Adresse, sondern das Foo mit seinem x direkt. Und im folgenden Code

    fn main() {
        let v: Vec<i32> = vec![1,2,3];
    }
    

    ist auch v kein Zeiger auf einen Vec , v ist ein Vec . Dass ein Vec intern natürlich einen Zeiger speichert, über den die Elemente erreicht werden können, sollte jedem klar sein, weil Vec<i32> (indirekt) beliebig viele davon speichern können soll und das geht eben nur, indem man dafür auf den Heap-Speicher ausweicht. Logisch gesehen sind die Elemente aber in dem Vec drin. Die Indirektion ist nur ein Implementierungsdetail von Vec .

    Klar soweit?


Anmelden zum Antworten