Kopieren im Array



  • Hallo!

    Wenn ich ein dynamisches Array habe, in das ich einen Wert einfüge, dann muss ich ja das Array um eins vergrößern und alle anschließenden Werte um eins hochkopieren. Genauso beim Löschen: Alle anschließenden Werte müssen um eins zurück kopiert werden. (Eine Liste möchte ich wegen der längeren Zugriffszeiten nicht benutzen und die Standardlibrary benutzt, wenn ich die Testzeiten vergleiche, scheinbar genau die gleichen Kopiermechanismen, ebenso der Befehl copy).

    Wenn ich z.B. ein Integer-Array habe und weiß, der zu kopierende Bereich beginnt ab Speicherstelle X + 4*Anzahl der zu kopierenden Werte, gibt es einen Befehl, mit dem man den Speicher in einem Rutsch kopieren kann? Das müsste doch dann viel schneller gehen, als wenn ich alles einzeln kopiere. Da C++ auch für die Programmierung von Videospielen benutzt wird, müssten Speicherkopiervorgänge doch auch viel schneller möglich sein.

    Ich habe beim Googeln den Befehl memmove entdeckt, kann man den dafür benutzen? Leider gibts da kaum vernünftige Erklärungen zu...

    Viele Grüße + Danke, Marc



  • mit memmove kannst du Speicherblöcke bewegen, die sich überlappen. Wenn ich aber richtig verstanden habe, was du in deinem ersten Absatz geschrieben hast, dann ist das unnötig, weil realloc auf eine andere Stelle zeigen kann aber garaniert, dass der bisherige Inhalt bestehen bleibt (sowohl beim Vergrößern als auch beim Verkleinern des dynamischen Speichers).

    Was findest du denn "unvernünftig" an man: memmove(3)? Da steht alles drin, was man braucht.



  • Wenn dein Array groß ist, wird ein memmove nicht schneller sein. Der Bottleneck ist der Zugriff auf den Speicher. Auf werden das normale Kopieren und das memmove meistens warten. Kann sein, dass das memmove länger wartet, da es effizienter ist.

    Was in einigen Fällen sinnvoll sein kann, ist eine Verschiebung des Speichers ohne, dass die Caches berührt werden. Denn so müllt man sich diese nicht mit sinnlosen Daten voll.

    Das ist aber prozessorspezifisch soweit ich weiss.



  • memmove ist sowieso nicht schneller. man: memcpy(3) ist schneller, wenn sich Quelle/Ziel nicht überlappen. Aber afaik hat std::copy zumindest bei der libstdc++ dafür Spezialisierungen.

    Einfacher könntest Du es machen, wenn Dir die Sortierung nicht wichtig ist. Dann müsstest Du jeweils nur einen Wert kopieren. Beim anfügen solltest Du nicht immer einzeln erhöhen, sondern direkt mehr Speicher anfordern. Speicherallozieren ist eine sehr teure Operation. Schau Dir doch einfach mal std::vector an.



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Linux/Unix in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hi ihr!

    Danke erstmal für eure Antworten! Ich geht um Strukturen und ich teste erstmal aus, wie das Ganze funktioniert. Ich bekomme z.B beim unteren Code, der zunächst innerhalb des Arrays noch gar nichts kopiert, entweder einen Segmentation fault oder "*** glibc detected *** realloc(): invalid pointer: 0x080489dd ***". Ich entdecke da keinen Fehler und die Werte sollen nachher alphabetisch geordnet werden. Das, was die STL macht, muss man doch auch "manuell" machen können, oder?

    struct uidaten{
      char nick[26];
      int nr;
    };
    
    int hinzu(char nick[26],uidaten *userindex,int &altl){
      userindex = (uidaten *)realloc(userindex,(altl+1)*sizeof(uidaten));
      strcpy(userindex[altl].nick,nick);
      userindex[altl].nick[sizeof(userindex[altl].nick)-1]=0;
      userindex[altl].nr=altl;
      altl++;
      return 0;
    }
    
    int main()
    {
    uidaten *userindex;
    int l=0;
    i=hinzu("Anna",userindex,l);
    i=hinzu("Caesar",userindex,l);
    ...
    

    Viele Grüße, Marc



  • Variablen immer initialisieren.
    Zudem resultiert

    userindex = (uidaten *)realloc(userindex,(altl+1)*sizeof(uidaten));
    

    potentiell in einem Speicherleck (wenn auch der darauf folgende Code dann sowieso zu ein segfault führen würde).
    strcpy ist böse und kopiert auch den Terminator, dass muss also nicht noch extra getan werden.



  • Hi!

    camper schrieb:

    Variablen immer initialisieren.
    Zudem resultiert

    userindex = (uidaten *)realloc(userindex,(altl+1)*sizeof(uidaten));
    

    potentiell in einem Speicherleck (wenn auch der darauf folgende Code dann sowieso zu ein segfault führen würde).

    Vielleicht ist die Frage etwas doof, aber was würdest du an dem Code konkret ändern, damit er nicht mehr die Fehlermeldungen anzeigt? Realloc hat ja die Aufgabe, den Speicher zu erweitern und ggf. den Speicherbereich zu verschieben (mit automatischer Änderung der Zeigeradresse) - so hab ich ihn zumindest überall im Netz erklärt gesehen.

    camper schrieb:

    strcpy ist böse und kopiert auch den Terminator, dass muss also nicht noch extra getan werden

    Ich bin noch nicht so lange bei C++. Muss man nicht einen Terminator reinsetzen, damit das Programm weiß, wo der Nickname tatsächlich aufhört? (26 ist ja nur die Maximalgröße).

    Viele Grüße, Marc


Anmelden zum Antworten