sehr viele Listen kopieren



  • Hallo,

    mal angenommen, ich habe ein Programm, das ständig Listen kopieren muß, und zwar so schnell wie möglich und nicht nur die Pointer sondern die kompletten Objekte, dann kann ich das ja z.B. so machen:

    std::list<Object*> list;
    std::list<Object*> copy;
    
    std::list<Object*>::iterator iter = list.begin();
    
    while(iter != list.end())
        copy.push_back(new Object(**iter));
    

    Allerdings ist das natürlich etwas zeitraubend, da ich die Objekte alle über den Copykonstruktor kopieren muß und natürlich komplett über die alte Liste iteriere.

    Cool wäre es, wenn ich einfach per memcopy einen kompletten Speicherbereich kopieren könnte. Das würde gehen, wenn ich Arrays verwende und keine Listen. Aber es muß in meinem Fall definitiv eine Liste sein - möglicherweise sogar ein Tree (ist noch nicht ganz sicher).

    Gibt es da auch irgendwie eine Möglichkeit, dafür zu sorgen, daß alle Objekte schön hintereinander liegen? Also sowohl bei 'ner Liste als auch bei 'nem Tree? Oder kommt man da um Arrays nicht drumrum?

    Der vector-Container benutzt intern soweit ich weiß Arrays. Wäre es damit evtl. möglich? Ich nehme mal an, dann dürfte ich halt keine Pointer verwenden sondern müßte die Objekte direkt drin speichern.

    Hat jemand 'ne Idee?



  • list oder map kann man nicht mit memcpy kopieren.
    vector geht ohne Probleme mit memcpy.



  • templäd schrieb:

    list oder map kann man nicht mit memcpy kopieren.
    vector geht ohne Probleme mit memcpy.

    Auch für nicht-PODs mit überladenem operator= ? Nicht, dass ich wüsste. Dafür ist 'std::copy' da.



  • copy.push_back(new Object(**iter));

    mach daraus ein

    copy.push_back(*iter);

    wenn du nicht kopieren willst.

    und lass memcpy in ruhe. memcpy ist idR die falsche antwort - egal worum es geht.



  • Richtig. Für nicht PODs geht's natürlich nicht 😉
    Aber memcpy als schön gekapselten Optimierungsmaßnahme ist vollkomen ok.
    Sollte man natürlich erst dann machen, wenn klar ist, dass das std::copy der Flaschenhals ist.



  • Shade Of Mine schrieb:

    copy.push_back(new Object(**iter));

    mach daraus ein

    copy.push_back(*iter);

    wenn du nicht kopieren willst.

    und lass memcpy in ruhe. memcpy ist idR die falsche antwort - egal worum es geht.

    Naja mir geht's schon ums Kopieren 😉 daher muß ich da schon den Copy-Konstruktor aufrufen.

    Aber stimmt, mit memcpy wird's problematisch sobald innen drin nochmal Pointer sind. Hängt dann aber irgendwie auch vom Anwendungsfall ab, es könnte ja durchaus sein daß es okay ist, wenn es keine Deep-Copy wird.

    std::copy kenne ich noch nicht, das werd ich mir mal anschauen.



  • Also wenn ich std::copy einsetze, dann geht es immerhin 4x so schnell. Allerdings muß ich dann natürlich Object und nicht Object* speichern. Werde mir das als mögliche Lösung mal offenhalten.

    Vielen Dank schonmal!


  • Administrator

    Naja, wenn du die Objekte kopieren möchtest, auf welche der Zeiger in der Liste zeigt, dann gibt es da auch ein paar Möglichkeiten. Eine wäre zum Beispiel folgendes:

    #include <iterator> // std::back_inserter
    #include <algorithm> // std::transform
    
    struct CopyValue
    {
      template<typename ValueT>
      ValueT* operator ()(ValueT const* const pvalue)
      { return new ValueT(*pvalue); };
    };
    
    std::list<Object*> list;        // Erste Liste
    std::list<Object*> resultList;  // Zweite Liste
    
    // Kopiervorgang:
    std::transform(list.begin(), list.end(), std::back_inserter(resultList), CopyValue());
    

    Natürlich dann das delete auf allen Objekten in der zweiten Liste nicht vergessen 😉

    Grüssli


Anmelden zum Antworten