Konstante Referenz wird ungültig?!



  • Hi,

    habe ein Problem mit folgendem Code:
    http://pastebin.com/9gNVpjMP

    Mittels Debugging habe ich herausgefunden, dass beim ersten Aufrufen der Funktion "branchPath" der als konstanten Referenz übergebene "Path" undefiniert wird.
    Ich habe keine Erklärung dafür. Nach dem ersten Erzeugen eines neuen Pfades verliert das Objekt offenbar seinen definierten Wert.

    D.h.

    void branchPath(const Path& path, std::vector<Path>& alive_path)
    {
        Point position = path.m_path.back();
        for(auto& dir: direction){
            Point p = position + dir;
            if(field[Coord2Vec(position + dir)] == 0 and dir != path.m_dir){
                Path new_path(position, path.m_path, dir);
                alive_path.push_back(new_path);
            }
        }
    }
    

    "path" scheint "ungültig" zu werden. Wie kann das sein und was kann ich dagegeben tun?!

    Vielen Dank für jede Hilfe, in diesem Fall habe ich wirklich keine Ahnung wo der Fehler liegen könnte.



  • beim zufügen an einen std::vector werden alle iteratoren, zeiger und Referenzen auf dessen elemente ungültig.


  • Mod

    roflo schrieb:

    beim zufügen an einen std::vector werden alle iteratoren, zeiger und Referenzen auf dessen elemente ungültig.

    Noch als Zugabe der Hinweis, dass sie trotz Einfügens garantiert gültig bleiben, sofern Size < Capacity. Das heißt, mittels vorherigem reserve kann man sicher stellen, dass das nicht passiert (Natürlich macht dafür das reserve selber alles kaputt).



  • Und wie so oft fühl ich mich nach euren Antworten doof, haha.

    Vielen Dank 🙂
    Jetzt wo ihr es sagt ist es offensichtlich, aber ich hatte "const &" als "sicher" in meinem Kopf abgespeichert.



  • kingcools schrieb:

    Und wie so oft fühl ich mich nach euren Antworten doof, haha.

    Musst Du nicht.

    kingcools schrieb:

    Jetzt wo ihr es sagt ist es offensichtlich, aber ich hatte "const &" als "sicher" in meinem Kopf abgespeichert.

    C++ ist nicht speichersicher. Man muss sich immer Gedanken dazu machen, worauf sich ein roher Zeiger oder eine Referenz bezieht und wie lange das, worauf sich der Zeiger/die Referenz bezieht, gültig ist. Die sind ja nicht "besitzend" sondern nur "ausleihend". 🙂

    Es gibt in diesem Fall noch eine Alternative: Mit std::deque geht sowas. std::deque macht die Garantie, dass wenn man ganz am Anfang oder ganz am Ende ein neues Element einfügt, die Referenzen alle noch gültig bleiben. Nur die Iteratoren werden ungültig. Und wenn man irgendwo in der Mitte einfügt, dann werden die Referenzen auch noch ungültig. Aber dafür bietet die deque eben noch den schnellen Zugriff (random access).

    Mit der Programmiersprache Rust wär' das jetzt nicht passiert. Der Compiler hätte dich davon abgehalten, den Vektor zu verändern, solange der wegen einer einer Referenz auf eines seiner Elemente als "ausgeliehen" gilt. 🙂

    SCNR!


  • Mod

    C++ ist nicht speichersicher. Man muss sich immer Gedanken dazu machen, worauf sich ein roher Zeiger oder eine Referenz bezieht

    Muss man das? Ich kann mich nicht erinnern jemals lange darüber nachgedacht zu haben, und auch nur selten kurz.


Log in to reply