Nulltes Element eines leeren std::vectors



  • Eine kurze Frage zur STL. Führt

    std::vector<T> v;
    T* ptr = &v[0];
    

    zu undefiniertem Verhalten?

    Der C++-Standard sagt zwar Folgendes:

    §23.2.4/1 Class template vector schrieb:

    A vector is a kind of sequence that supports random access iterators. In addition, it supports (amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage management is handled automatically, though hints can be given to improve efficiency. The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool , then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size() .

    Wie ich das sehe:

    • Aus der Gleichheit &v[0] == &v[0] + 0 schliesse ich nicht, dass v[0] bei leeren Containern überhaupt definiert ist.
    • Zumal im Fall von v.size() == 0 das Intervall 0 <= n < 0 angegeben ist (also eine leere Menge), scheint es mir eher so, als hätte man diesen Fall im Standard nicht miteinbezogen.
    • Generell ist ja die Semantik von v[n] über *(v.begin() + n) definiert. Bei leeren Containern gilt v.begin() == v.end() , wodurch man den Past-The-End-Iterator dereferenziert, also undefiniertes Verhalten hat.

    Meiner Ansicht nach weist alles auf UB hin, sieht das jemand anders? Ist halt etwas schade, weil es die Generizität (gerade in Verbindung mit C-APIs) ziemlich einschränkt und Fallunterscheidungen nötig macht. Zumindest sofern man das streng nimmt.



  • also einen leeren vector vorausgesetzt...

    &v[0] kann IMO nicht definiert sein, da v[0] eine Referenz zurückgeben muss (ausgenommen vector<bool> natürlich).
    und ich fände es äusserst fragwürdig, wenn der vector zu diesem zweck einfach ein "dummy-element" anlegen bzw. eine (im derzeitigen standard "verbotene" bzw. nicht klar erlaubte) "null-referenz" zurückgeben dürfte.
    da ich also keinen "erlaubten" rückgabewert für v[0] wüsste, behaupte ich einfach mal dass es UB sein muss. und noch ein "&" davorzustellen ändert daran nichts.



  • Gibt es einen plausiblen Grund v[n] mit n==0 anders zu behandeln als jedes andere n, das die (un)Gleichun 0 <= n < v.size() nicht erfüllt? Ich denke nicht.



  • Wozu man so ein Quatsch auch brauchen soll???


  • Mod

    Nexus schrieb:

    Ist halt etwas schade, weil es die Generizität (gerade in Verbindung mit C-APIs) ziemlich einschränkt und Fallunterscheidungen nötig macht. Zumindest sofern man das streng nimmt.

    Bei C musste auch prüfen, ob du nicht ein Array mit 0 Elementen hast. Das Verhalten von malloc(0) ist "implementation defined" entweder Nullzeiger oder ein ungültiger anderer Zeiger.



  • Ich finde einen Zeiger auf ein Array das es nicht gibt schon toll.



  • v[0] ist bereits nicht definiert, da 0<vec.size() gelten muss. das wird nur nicht abgefangen, siehe at().



  • Danke allen für die Bestätigung.

    @ naaaaa und SeppJ:
    Ich dachte halt an sowas:

    c_write_array(&v[0], v.size());
    

    Bei v.size() == 0 würde dann einfach nichts getan. Halt wie die STL-Algorithmen, welche ebenfalls mit leeren Sequenzen umgehen können.


Anmelden zum Antworten