unorderd_map emplace



  • Ruvi schrieb:

    lolbot schrieb:

    lol? In welchem Container sollte es je einen Unterschied zwischen kopieren und in-place erstellen geben?

    Versteh jetzt nicht ganz was es da zu lol'en gibt.

    Weil es falsch ist. vector::emplace_back nach Standard eine Strong Exception Guarantee (vorausgesetzt die Elemente sind kopierbar oder noexcept move-bar).

    Ruvi schrieb:

    Das ist bei emplace oder emplace_back nicht der Fall da die Datenstruktur in jedem Fall veraendert ist, da du dass Objekt innerhalb der Datenstruktur erstellst.

    Also das Objekt existiert noch gar nicht, wenn eine Ausnahme geworfen wurde.

    Zu deinem Beispiel: Sieht für mich nach einem Bug in deiner Standardbibliothek aus. Passiert das bei push_back nicht?

    Die Aussage

    Der Speicher der alloziert wurde
    //kann nicht weggeraeumt werden da man ansonsten die komplette
    //Datenstruktur neubauen muesste.

    verstehe ich nicht. Wo genau ist das Problem mit
    1. Speicher allokieren
    2. Neues Element erzeugen. Falls Ausnahme => Speicher freigeben
    3. Alte Elemente kopieren. Falls Ausnahme => Elemente löschen, Speicher freigeben.
    4. Alte Elemente löschen, Zeiger umbiegen, Speicher freigeben.

    Nebenbei geht es hier um unordered_map und dürfte emplace auch in deiner seltsame Standardbibliothek keinen Unterschied machen.



  • Ruvi schrieb:

    P.S.: Das ganze Problem an der Sache wird einem nochmal deutlicher, wenn in meiner Klasse Foo jetzt noch ein paar ints sind und ich versuche 100.000 Pushbacks zu machen, die scheitern weil irgendwas generelles nicht geht.

    Du hast dann mit anderen Worten einen riesigen leeren Vector rumliegen der unter Umstaenden hunderte von MB Speicher belegt und das alles nur weil Du dir ein copy/move ersparen wolltest.

    Glaube ich nicht. Kannst du das nachweisen?



  • lolbot schrieb:

    Glaube ich nicht. Kannst du das nachweisen?

    Interessant, Du hast recht.
    Ich bin jetzt davon ausgegangen, dass sich das Problem addiert.

    Nichtsdestotrotz habe ich mit push_back nicht das Problem, dass sich die Kapazitaet veraendert, weil das Objekt ausserhalb des Vectors erstellt wird.

    Bei emplace_back bleibt der Vector mit 1 Capacity stehen in meinem Beispiel.
    Vielleicht kann ja jemand anderes nochmal gucken aber die Strong exception gurantee waere damit nicht gegeben.



  • Scheint ein Problem mit dem VC++ zu sein.

    #include <vector>
    #include <stdexcept>
    #include <iostream>
    using namespace std;
    
    struct AlwaysThrow {
        AlwaysThrow(){ throw(std::runtime_error("Error")); }
    };
    struct ThrowOnCopy {
        ThrowOnCopy()=default;
        ThrowOnCopy(ThrowOnCopy const&) { throw(std::runtime_error("Error")); }
    };
    
    int main() {
        {
            vector<AlwaysThrow> v;
            try { v.emplace_back(); }
            catch (...) { std::cout << v.size() << "/" << v.capacity() << '\n'; }
        }
        {
            vector<ThrowOnCopy> v;
            try { v.push_back(ThrowOnCopy()); }
            catch (...) { std::cout << v.size() << "/" << v.capacity() << '\n'; }
        }
    }
    

    Gibt mit gcc und clang jeweils 0/0 aus, mit vc++ allerdings 0/1. Bei ThrowOnCopy darf alles passieren (nur Basic Guarantee), im ersten Fall sollte aber meinem Verständnis nach 0/0 herauskommen.

    Hat jemand Lust, einen Bugreport zu erstellen?

    [vector.modifiers]/1 schrieb:

    template <class... Args> void emplace_back(Args&&... args);
    

    Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all the iterators and references before the insertion point remain valid. If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation there are no effects. If an exception is thrown by the move constructor of a non- CopyInsertable T , the effects are unspecified.

    PS: @Microsoft: lol!



  • lolbot schrieb:

    Hat jemand Lust, einen Bugreport zu erstellen?

    Ich habe mal einen erstellt> https://connect.microsoft.com/VisualStudio/feedback/details/1653220



  • Ruvi schrieb:

    lolbot schrieb:

    Hat jemand Lust, einen Bugreport zu erstellen?

    Ich habe mal einen erstellt> https://connect.microsoft.com/VisualStudio/feedback/details/1653220

    Das Problem (wenn es überhaupt eins ist) ist bei VS2015 auch noch vorhanden. Mal sehen wann sich STL meldet. 😃



  • BTW: Ist bei std::vector ne "small object optimization" erlaubt (wie z.B.: bei std::string )?
    Das ist zwar nicht das Problem (hab's extra ausprobiert - .capacity() ist for dem erfolglosen emplace wirklich 0), aber würde mich interessieren ob eine Implementierung das machen darf.





  • Cool, danke 🙂



  • Da hier niemand irgendwas wirft, klappt emplace. 🙂

    operator[] geht auch, stimmt.

    Danke!


Anmelden zum Antworten