kurze Frage zu std::vector



  • Hallo Leute,

    ich habe mal eine Frage zu std::vector. Kurz gesagt: ich möchte einen unsigned char Puffer in einen std::vector wandeln.
    Hier mal der Codeausschnitt:

    vector<unsigned char> encodedData;
    unsigned char *outData = nullptr;
    int size = 0;
    
    size = encodeFunction(..., &outData) // setzt den pointer auf die kodierten Daten und gibt die größe der Daten zurück
    
    if (outData != nullptr)
    {
        encodedCms.assign(outData, outData + size);
        free(outData);
    }
    

    Ich habe eine Biblotheksfunktion, die Daten kodiert und das Ergebnis als 2 Variablen ('outData' und 'size') zurückliefert. Nun arbeite ich mittlerweile lieber mit std::vector und die Überlegung war, wie ich die Daten am besten in den vector packe. Zuvor hatte ich meist via for-Schleife und .push_back() die Bytes einzeln hineinkopiert. ...das wollte ich nun mal besser machen. Nun bin ich auf folgendes gestoßen:

    encodedCms.assign(outData, outData + size);
    

    Das geht wunderbar, aber warum muss ich im 2. Parameter nochmal 'outData' angeben, anstatt nur 'size'? Das hier geht nicht:

    encodedCms.assign(outData, size);
    

    Gibt es auch die Möglichkeit, dass ein bereits allozierter Speicher von std::vector direkt übernommen wird (move statt copy)? Die Lib-Funktion alloziert den speicher allerdings mit malloc anstatt mit new.


  • Mod

    SBond schrieb:

    Das geht wunderbar, aber warum muss ich im 2. Parameter nochmal 'outData' angeben, anstatt nur 'size'?

    Das ist eben einfach so im Design der C++-Standardbibliothek so, dass man Bereiche stets in der Form <Anfang, Ende>, anstatt <Anfang, Länge> angibt. Das hat auch ein paar gewaltige Vorteile. Beispielsweise muss man eben nicht die Länge kennen. Es genügt, wenn man weiß, wie das Ende aussieht, was meistens einfacher zu wissen ist als die tatsächliche Größe eines Bereichs. Daher solltest du dir diese Art und Weise möglichst auch angewöhnen.

    Gibt es auch die Möglichkeit, dass ein bereits allozierter Speicher von std::vector direkt übernommen wird (move statt copy)? Die Lib-Funktion alloziert den speicher allerdings mit malloc anstatt mit new.

    Nein, gibt es nicht. Ich würde hier aber das Design der Bibliotheksfunktion als fehlerhaft ansehen. Ist die Funktion von dir? Falls ja, ändere sie. Eine Funktion, die einen Text codiert, sollte nichts mit Speicherallokation am Hut haben.



  • vielen Dank für die Hilfe 🙂

    SeppJ schrieb:

    Ist die Funktion von dir? Falls ja, ändere sie. Eine Funktion, die einen Text codiert, sollte nichts mit Speicherallokation am Hut haben.

    nein. Das ist eine OpenSSL-Funktion.



  • Du könntest folgendes tun: http://ideone.com/6D04Fk
    aber das solltest du nicht 😉

    Im Grunde hast du zwei Probleme zu lösen:

    1.: Deine Daten wurden mit malloc alloziiert, nicht mit new[].
    Deshalb brauchst du einen eigenen allocator, der mit free aufräumt.

    2.: std::vector bietet keinen Konstruktor, der dir erlaubt direkt irgendwelche zeiger reinzufüttern.

    Ersteres wird mit dem "mallocator" gelöst, einfach ein weitestgehend vollständiger std::allocator-Ersatz, der malloc/free nutzt.
    Das zweite Problem ist schwieriger, weil du hier nicht um implementation defined behaviour rumkommst.
    Die Lösung bezieht sich auf die libstdc++ und wird mit MSVC nicht funktionieren.

    Der Trick hier funktioniert, weil std::vector im Standardkonstruktor nocht keinen Speicher anfordert, deshalb brauchen wir in unserem custom Konstruktor auch nicht aufräumen. Danach schreiben wir einfach Anfang und Ende direkt in den vector.

    Will man nun statt des eigenen raw_vector einen normalen std::vector haben, so reicht ein einfaches std::move in einen std::vector.



  • ah ok.
    Danke für die Hinweise 😃


Anmelden zum Antworten