Range based for Loop



  • Hier eine Übungsaufgabe aus meinem C++ Kurs. Die Frage lautet warum vor dem e zweimal das && Symbol steht. Ich habs durchprobiert und bekomme mit und ohne dem Ampersand die gleiche Ausgabe, hat jemand ne Idee was das für einen Unterschied macht.

    int main()
    {
        vector <bool> d(42);
        for (bool &&e : d) e = false;
        
    }
    

    Danke schonmal im Vorraus:)


  • Mod

    Welche Ausgabe hast du denn bekommen? Derzeit gibt das Programm ja gar nichts aus, aber irgendetwas wirst du ja noch gemacht haben bei deinen Experimenten.

    Was bedeutet das && in dem Zusammenhang deines Wissens nach?



  • @SeppJ
    Welche Ausgabe hast du denn bekommen?
    Ich habe in jeder Iteration einfach nur den Wert von e ausgeben lassen, wodurch ich 42x den Wert 0 / false in der Konsole hatte. Diese Ausgabe hat sich mit und ohne dem && nicht verändert.

    Was bedeutet das && in dem Zusammenhang deines Wissens nach?
    Das Ampersand habe ich bis jetzt nur als Referenz kennengelernt, was in diesem Kontext für mich keinen Sinn ergibt, da e ja nicht als alias für eine andere Variable verwendet wird.



  • Beachte, dass du hier einen std::vector<bool> hast. Was ist daran speziell, was unterscheidet den std::vector<bool> zum Beispiel vom std::vector<int>? Es gibt da einen bedeutenden Unterschied!

    Bist du sicher, dass da nicht for (auto &&e : d) steht, also mit auto&& statt bool&&?



  • @maku2207 sagte in Range based for Loop:

    Ich habe in jeder Iteration einfach nur den Wert von e ausgeben lassen, wodurch ich 42x den Wert 0 / false in der Konsole hatte. Diese Ausgabe hat sich mit und ohne dem && nicht verändert.

    Dann versuch doch auch mal, true zuzuweisen. Immer noch alles 0? Hm, macht die Zuweisung dann überhaupt irgendwas?

    Das Ampersand habe ich bis jetzt nur als Referenz kennengelernt, was in diesem Kontext für mich keinen Sinn ergibt, da e ja nicht als alias für eine andere Variable verwendet wird.

    Die Referenz in einer for-Loop ergibt aber Sinn, wenn man die Elemente des vectors ändern will. Beginne einfacher: nimm einen vector<int> (statt bool) und schreibe die Schleife erneut. Einmal mit einem & und einmal ohne. Ist dir dabei der Unterschied klar? Danach guck dir vector<bool> an, der ist nämlich speziell. Warum kompiliert der Code zum Beispiel nicht mehr, wenn deine Loop-Variable ein & hat und du einen vector<bool> hast? Das solltest du erstmal beantworten können.



  • @wob
    Was ist daran speziell, was unterscheidet den std::vector<bool> zum Beispiel vom std::vector<int>?
    So wie ich das verstanden habe, alloziert ein bool vector pro Element jeweils 1 Byte auf dem Heap, während ein int vector 4 Bytes reservieren würde.

    Bist du sicher, dass da nicht for (auto &&e : d) steht, also mit auto&& statt bool&&?
    Ich hab dir hier mal einen Screenshot von der gesamten Aufgabe gemacht

    Edit: Ich habe gerade deine 2. Antwort gelesen und melde mich wenn ich es ausprobiert habe. Vielen Dank!



  • @maku2207 sagte in Range based for Loop:

    So wie ich das verstanden habe, alloziert ein bool vector pro Element jeweils 1 Byte auf dem Heap, während ein int vector 4 Bytes reservieren würde.

    Der wesentliche Unterschied ist, dass ein vector<bool> eine völlig andere Implementierung als die anderen vectoren haben kann. Zum Beispiel kann 1 Bit pro Element verwendet werden. - das bedingt aber, dass der Zugriff auf einzelne Elemente nicht mehr ein direkter Speicherzugriff sein muss. Die Daten des vector<bool> müssen auch nicht durchgehend und hintereinander im Speicher liegen. Da ist vieles erlaubt. The manner in which std::vector<bool> is made space efficient (as well as whether it is optimized at all) is implementation defined. (https://en.cppreference.com/w/cpp/container/vector_bool)



  • @wob
    Dann versuch doch auch mal, true zuzuweisen. Immer noch alles 0? Hm, macht die Zuweisung dann überhaupt irgendwas?
    Wenn meine Anweisung e = true lautet, wird sowohl mit als auch ohne && jedes Element des Vektors auf 1 gesetzt, da sehe ich leider keinen Unterschied.

    Beginne einfacher: nimm einen vector<int> (statt bool) und schreibe die Schleife erneut. Einmal mit einem & und einmal ohne. Ist dir dabei der Unterschied klar?
    Auch hier funktioniert der Code mit und ohne einem &, ich verstehe leider nicht was du meinst



  • @wob sagte in Range based for Loop:

    @maku2207 sagte in Range based for Loop:

    So wie ich das verstanden habe, alloziert ein bool vector pro Element jeweils 1 Byte auf dem Heap, während ein int vector 4 Bytes reservieren würde.

    Der wesentliche Unterschied ist, dass ein vector<bool> eine völlig andere Implementierung als die anderen vectoren haben kann. Zum Beispiel kann 1 Bit pro Element verwendet werden. - das bedingt aber, dass der Zugriff auf einzelne Elemente nicht mehr ein direkter Speicherzugriff sein muss. Die Daten des vector<bool> müssen auch nicht durchgehend und hintereinander im Speicher liegen. Da ist vieles erlaubt. The manner in which std::vector<bool> is made space efficient (as well as whether it is optimized at all) is implementation defined. (https://en.cppreference.com/w/cpp/container/vector_bool)

    Ah cool, das wusste ich nicht. Ich schau mal in die Dokumentation rein!


  • Mod

    @maku2207 sagte in Range based for Loop:

    @wob
    Dann versuch doch auch mal, true zuzuweisen. Immer noch alles 0? Hm, macht die Zuweisung dann überhaupt irgendwas?
    Wenn meine Anweisung e = true lautet, wird sowohl mit als auch ohne && jedes Element des Vektors auf 1 gesetzt, da sehe ich leider keinen Unterschied.

    Wirklich? Du gibst aber schon den Vektorinhalt aus? Du schriebst nämlich oben mal

    @maku2207 sagte in Range based for Loop:

    Ich habe in jeder Iteration einfach nur den Wert von e ausgeben lassen,

    Was natürlich nicht der Vektorinhalt ist.

    Und ich frag mal vorsichtig: Bist du sicher, dass du dein Programm bei deinen Experimenten überhaupt neu compilierst? Denn eigentlich dürfte bool &e : d gar nicht funktionieren, außer deine vector<bool>-Implementierung macht komische Sachen (und mit komischen Sachen meine ich normale Sachen, denn für vector<bool> ist es normal, dass er komisch ist 🙂 )

    PS: Findet es noch jemand interessant, dass der Code aus der Aufgabe quasi 1:1aus
    https://stackoverflow.com/questions/13130708/what-is-the-advantage-of-using-forwarding-references-in-range-based-for-loops
    ist? Ob der Lehrer überhaupt weiß, was der Code wirklich tut?



  • Dieser Beitrag wurde gelöscht!


  • @SeppJ sagte in Range based for Loop:

    Ob der Lehrer überhaupt weiß, was der Code wirklich tut?

    Oh, habe mir die Aufgabe gerade mal angeguckt. Ich würde sagen: nein. Denn die 2. Antwort, die als einziges irgendwie sinnvoll erscheint, ist auch nicht korrekt. Im Code wird nämlich mit bool &&e gerade keine "universal reference" verwendet (dazu müsste es ein Template bzw auto sein). (und nutzt man nicht statt "universal reference" heute "forwarding reference"?!)


  • Mod

    @wob sagte in Range based for Loop:

    @SeppJ sagte in Range based for Loop:

    Ob der Lehrer überhaupt weiß, was der Code wirklich tut?

    Oh, habe mir die Aufgabe gerade mal angeguckt. Ich würde sagen: nein. Denn die 2. Antwort, die als einziges irgendwie sinnvoll erscheint, ist auch nicht korrekt. Im Code wird nämlich mit bool &&e gerade keine "universal reference" verwendet (dazu müsste es ein Template bzw auto sein). (und nutzt man nicht statt "universal reference" heute "forwarding reference"?!)

    Exakt: https://ideone.com/qNr4eF
    Dachte sich wohl, der Code wäre so verständlicher, aber hat alles kaputt gemacht. Tja, da will ich den Schüler sehen, der dies korrekt erklären kann.



  • @SeppJ sagte in Range based for Loop:

    Wirklich? Du gibst aber schon den Vektorinhalt aus? Du schriebst nämlich oben mal

    Oh mann ey, da habe ich wohl nicht mitgedacht 😃 . Ich habe tatsächlich immer e ausgeben lassen und nicht den tatsächlichen Vektorinhalt. Da funktioniert die Zuweisung mit e = true sowohl mit als auch ohne && nicht mehr. Aber wieso funktioniert das Ganze mit auto? Ich dachte das ist nur ein "Datentyp" der sich den zu verwendenden, richtigen Datentyp aus dem Kontext zieht(also bool?).
    Was mich auch noch stutzig macht, ist, dass ich das doppelte Ampersand auch einfach weglassen kann und die Zuweisung funktioniert dennoch.

    Abgesehen davon schonmal vielen Dank @SeppJ und @wob für eure Hilfe!



  • std:.vector<bool> gibt beim operator[] eine spezielle reference zurück, welche einen einzelnen Wert (bit) adressieren kann. Da dieser jedoch auch über den operator bool verfügt, wird bei bool &&e : d keine veränderbare Referenz zurückgegeben, sondern ein Wert.
    Und bei auto &&e : d ermittelt der Compiler aber den korrekten Datentyp dafür: std::vector<bool>::reference &&e : d, und damit kann dann der vector-Wert verändert werden (s.a. mein, zu @SeppJ's hinzugefügter Ideone-Code).



  • @Th69 sagte in Range based for Loop:

    std:.vector<bool> gibt beim operator[] eine spezielle reference zurück, welche einen einzelnen Wert (bit) adressieren kann. Da dieser jedoch auch über den operator bool verfügt, wird bei bool &&e : d keine veränderbare Referenz zurückgegeben, sondern ein Wert.
    Und bei auto &&e : d ermittelt der Compiler aber den korrekten Datentyp dafür: std::vector<bool>::reference &&e : d, und damit kann dann der vector-Wert verändert werden (s.a. mein, zu @SeppJ's hinzugefügter Ideone-Code).

    Cool ich glaube ich habe es jetzt verstanden. Vielen Dank!


Anmelden zum Antworten