std::vector befüllen ohne copy constructor?



  • Hallo 🙂

    Wie kann man einen std::vector befüllen ohne das ein copy constructor aufgerufen wird? möglichst ohne etwas auf den Heap zu laden.
    Ich würde gerne folgende Zeile, die noch einen copy constructor aufruft, austauschen.

    vector.push_back(QSubPlotable(&m_ColPattern, &m_FGWidthOffset))
    

  • Mod

    Ich würde gerne folgende Zeile, die noch einen copy constructor aufruft

    Nicht seit C++11. Da wird die Temporary direkt an die rvalue-Referenz gebunden, die push_back nimmt.



  • ok und gibt es einen weg es auch vor c++11 zu machen?



  • swap



  • std::move?
    Direkt mit Vektorelementen arbeiten?





  • nwp3 schrieb:

    emplace_back

    Fail
    [quote="Namenloser324"]std::move?
    Fail



  • Fail schrieb:

    nwp3 schrieb:

    emplace_back

    Fail
    [quote=Namenloser324"]std::move?
    Fail

    Fail



  • Ohne C++11 willst du eh kein C++ benutzen, dann nimm lieber [beliebige andere Sprache].



  • cooky451 schrieb:

    Ohne C++11 willst du eh kein C++ benutzen, dann nimm lieber [beliebige andere Sprache].

    Äh.. Ja.
    Vlt wird es mir auch so gehen wenn ich c++11 benutzt habe, aber derzeit komme ich auch mit "normalem" c++ zurecht.
    Btw. warum ist c++11 wenn es so viel bietet noch kein Standard in allen SDKs? Das 11. gibts doch schon ne Weile.

    nwp3 schrieb:

    emplace_back

    Dankesehr.



  • cl90 schrieb:

    cooky451 schrieb:

    Ohne C++11 willst du eh kein C++ benutzen, dann nimm lieber [beliebige andere Sprache].

    Äh.. Ja.
    Vlt wird es mir auch so gehen wenn ich c++11 benutzt habe, aber derzeit komme ich auch mit "normalem" c++ zurecht.
    Btw. warum ist c++11 wenn es so viel bietet noch kein Standard in allen SDKs? Das 11. gibts doch schon ne Weile.

    Gibts doch schon. Das ist eine Sache des Compilers, d.h. bei einem aktuellen Compiler kannst du all die schönen Dinge machen.

    Wenn du externe Bibliotheken nutzt, kann es dir erstmal egal sein, wie die funktionieren. Prinzipiell sind (sollten) die gut getestet sein und auch eine ordentliche Performance (zumindest im Release Modus*) haben. Denn die ganzen C++11 Neuerungen einzupflegen ist en gutes Stück Arbeit. Zumal es auch fraglich ist, ob eine Refaktorisierung was bringt. Einzig Move-Semantics und RValue-Referenzen bringen Performance**.
    Wenn du aber neuen Code schreibst, dann lohnt es sich sehr stark C++11 zu nutzen, da das Codeschreiben dadurch schon flotter wird, wie ich finde.

    *: Ich erinnere mich da an SFML. Im Debug Modus lief mein Game mit 0.5 - 2 FPS, im Release mit über 400 😃

    **: Das ist eine harte Aussage, aber so nicht gemeint. C++11 bringt schon viel, aber ich zweifle an, dass eine komplette Refaktorisierung eines großen Codestücks so viel Nutzen bringt. RValues bringen der Performance noch was, aber alles andere dürfte nur Syntax Zucker sein, oder?


  • Mod

    alles andere dürfte nur Syntax Zucker sein, oder?

    range-based for?



  • Ja, sag ich doch.

    Das ist doch "nur" eine Kurzschreibweise für

    for(auto it = std::begin(cont); it != std::end(cont); ++it){}
    

    (oder ähnliches)
    oder verstehe ich da was falsch?

    Aber wo ist da durch den Standard definiert, dass es einen Performanceboost gibt?



  • Skym0sh0 schrieb:

    Einzig Move-Semantics und RValue-Referenzen bringen Performance**.

    **: Das ist eine harte Aussage, aber so nicht gemeint. C++11 bringt schon viel, aber ich zweifle an, dass eine komplette Refaktorisierung eines großen Codestücks so viel Nutzen bringt. RValues bringen der Performance noch was, aber alles andere dürfte nur Syntax Zucker sein, oder?

    Es war schon vorher in C++ möglich, verflixt schnelle Programme zu basteln. Es war auch schon in C möglich, sogar in Assembler. Allein es ist in C angenehmer als in Assembler, in altem C++ viel angenehmer als in C, und in C++11 (vor allem wegen range based for) angenehmer als in altem C++.



  • Ja, das stimmt.


  • Mod

    Skym0sh0 schrieb:

    (oder ähnliches)

    Und hier liegt der Hund begraben: Der end-Iterator wird bei deiner Schleife potenziell in jedem Durchlauf angefordert, während bei range-based for dieser (hier __end ) zwischengespeichert wird:

    {
        auto && __range = range-init;
        for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) {
            for-range-declaration = *__begin;
            statement
        }
    }
    

    Darüber hatten wir hier auch schon mal einen Thread.



  • @Arcoth: Stimmt. Trotzdem wählen Leute die Range-Based For primär wegen der Syntax. Dass dabei die Performance leicht besser sein kann, ist eher ein netter Nebeneffekt, vielen Entwicklern dürfte das gar nicht bekannt sein.



  • cooky451 schrieb:

    Ohne C++11 willst du eh kein C++ benutzen, dann nimm lieber [beliebige andere Sprache].

    So langsam muss man hier wirklich darauf achten, welche Antworten man ernst nehmen kann und welche nicht.



  • cl90 schrieb:

    Wie kann man einen std::vector befüllen ohne das ein copy constructor aufgerufen wird? möglichst ohne etwas auf den Heap zu laden.
    Ich würde gerne folgende Zeile, die noch einen copy constructor aufruft, austauschen.

    vector.push_back(QSubPlotable(&m_ColPattern, &m_FGWidthOffset))
    

    Wie immer: Mehr Information wär nett gewesen. Aber ich rate mal, dass QSubPlotable ein Typ und keine Funktion ist und dass Deine vector -Variable vom Typ vector<QSubPlotable> ist.

    Um etwas direkt in verschiedenen Containern zu erzeugen, ohne da etwas reinkopieren zu müssen, wurde in C++11 emplace hinzugefügt:

    vector.emplace_back(&m_ColPattern, &m_FGWidthOffset);
    

    Super wär's jetzt noch, wenn QSubPlotable movable würde (falls es das nicht schon ist). Dann könnte sich so ein Vektor auch relativ effizient vergrößern. Ansonnsten: Wenn du die Größe exakt kennst, kannst du natürlich auch vor den ganzen push/emplace_backs schon vector<>::reserve aufrufen.

    Wenn ein QSubPlotable jetzt etwas großes, unhandliches ist, was einen teuren Copy-Ctor und keinen Move-Ctor hat, könnte man es ja dann noch mit einer Indirektion versuchen, also unique_ptr<QSubPlotable> oder so.

    Auch wichtig: Den Kram messen, wenn es um Geschwindigkeit geht.



  • kkaw schrieb:

    cl90 schrieb:

    Wie kann man einen std::vector befüllen ohne das ein copy constructor aufgerufen wird? möglichst ohne etwas auf den Heap zu laden.
    Ich würde gerne folgende Zeile, die noch einen copy constructor aufruft, austauschen.

    vector.push_back(QSubPlotable(&m_ColPattern, &m_FGWidthOffset))
    

    Wie immer: Mehr Information wär nett gewesen. Aber ich rate mal, dass QSubPlotable ein Typ und keine Funktion ist und dass Deine vector -Variable vom Typ vector<QSubPlotable> ist.

    Um etwas direkt in verschiedenen Containern zu erzeugen, ohne da etwas reinkopieren zu müssen, wurde in C++11 emplace hinzugefügt:

    vector.emplace_back(&m_ColPattern, &m_FGWidthOffset);
    

    Super wär's jetzt noch, wenn QSubPlotable movable würde (falls es das nicht schon ist). Dann könnte sich so ein Vektor auch relativ effizient vergrößern. Ansonnsten: Wenn du die Größe exakt kennst, kannst du natürlich auch vor den ganzen push/emplace_backs schon vector<>::reserve aufrufen.

    Wenn ein QSubPlotable jetzt etwas großes, unhandliches ist, was einen teuren Copy-Ctor und keinen Move-Ctor hat, könnte man es ja dann noch mit einer Indirektion versuchen, also unique_ptr<QSubPlotable> oder so.

    Auch wichtig: Den Kram messen, wenn es um Geschwindigkeit geht.

    Ich hab es jetzt letztendlich auf dem Heap gelöst. also
    vector.pushback(new bla());
    mit entsprechenden deletes an anderen stellen.
    Danke für die Ausführung. Ich werde mir das zu einem späteren Zeitpunkt zusammen mit c++11 wieder ansehen.


Anmelden zum Antworten