Funktion: vector<int> umkehren und zurück geben



  • Hallo zusammen,

    Ich will zwei Funktionen schreiben. Beide sollen die Elemente eines std::vector<int> in ihrer Reihenfolge umkehren. Sprich 1 2 3 4 wird zu 4 3 2 1.

    Die eine Funktion soll dies direkt an dem übergebenen vector machen, die andere soll einen neuen erzeugen und den ursprünglichen vector nicht verändern.

    void reverse_vec_self(std::vector<int> &vec)
    {
        for(unsigned i=0; i != vec.size()/2; ++i)
            std::swap(vec[0 + i], vec[(vec.size()-1) - i]);
    }
    // kann man das, ausgehend von einem vector<int>, noch besser machen?
    

    Meine Frage ist: Wieso ist der zurückgegebene vector der folgenden Funktion leer? Zumindest bin ich zu dem Schluss gekommen:

    std::vector<int>& reverse_vec(const std::vector<int> &vec)
    {
        std::vector<int> reversed;
    
        for(int i = vec.size() - 1; i < 0; --i)
        {
            reversed.push_back(vec[i]);
        }
    
        return reversed;
    }
    

    Ich hoffe jemand kann mir weiter helfen!

    lg
    HarteWare



  • Da i < 0 false ist, wird die Schleife nie durchlaufen. PS: Es gibt std::reverse. 😉



    1. ginge mit std::reverse kürzer
    2. Du gibst eine Referenz zurück, das ist böse. Gib per value zurück, das ist hier mindestens genauso schnell.


  • Von der Bedingung abgesehen, geht letzteres auch kürzer:

    return std::vector<int>(vec.rbegin(),vec.rend());
    


  • Ach wie blöd, gleich mal "weiter laufen wenn" verwechselt mit "aufhören wenn", danke!

    Werde mir die anderen Möglichkeiten merken, das war halt gemacht mit den Dingen, die ich bisher kannte.

    Jedenfalls danke für die Hilfe, hätt ich bissle schärfer schauen müssen...

    lg
    HarteWare

    P.S.: Ist die Rückgabe einer Referenz wirklich potenziell gefährlich? Ich hab halt gelesen, dass bei Vektoren (wenn sie viele, viele Elemente besitzen) das generell "billiger" ist...



  • HarteWare schrieb:

    P.S.: Ist die Rückgabe einer Referenz wirklich potenziell gefährlich? Ich hab halt gelesen, dass bei Vektoren (wenn sie viele, viele Elemente besitzen) das generell "billiger" ist...

    Es ist einfach grob falsch, denn deinen Vektor gibt es nach dem Verlassen der Funktion überhaupt nicht mehr. Du hast hier also keine Wahl.
    Das zurückgeben per value ist seit C++11 auch nicht mehr teuer, denn der lokale vector kann in den Rückgabewert gemovet werden.



  • ifsw schrieb:

    Das zurückgeben per value ist seit C++11 auch nicht mehr teuer, denn der lokale vector kann in den Rückgabewert gemovet werden.

    Das rückgeben per value ist schon seit C++98 gratis.



  • Alles klar, danke für die Erklärung 🙂 .
    Wobei ich ganz provokant sagen muss, funktioniert hats trotzdem und warnen tut mich der Compiler auch nicht, wobei der sowas mit Leichtigkeit erkennen könnte
    Aber ich mag diese Einstellung nicht, in dem Sinne...

    lg
    HarteWare



  • ungültigereferenz schrieb:

    Das rückgeben per value ist schon seit C++98 gratis.

    Konnte man bisher nicht so pauschal behaupten, da es in komplizierten Situationen (Exceptions, mehrere return paths) manchmal eben doch nicht gegriffen hat und diese Unsicherheit hat viele dazu getrieben, das ganze selbst in den unkomplizierten Situationen zu vermeiden.

    Mit C++11 hat man aber nun eine Garantie, dass das Objekt nicht kopiert wird. Insbesondere funktioniert das ganze nun auch mit Klassen, die erst gar keinen Kopierkonstruktor haben (freilich brauchen sie dann einen Move-Konstruktor).



  • HarteWare schrieb:

    Wobei ich ganz provokant sagen muss, funktioniert hats trotzdem

    Nur weil ein Programm gar nicht oder nur hin und wieder abstürzt nicht bedeutet nicht, dass es korrekt ist oder auch nur ansatzweise etwas sinnvolles tut.

    HarteWare schrieb:

    und warnen tut mich der Compiler auch nicht, wobei der sowas mit Leichtigkeit erkennen könnte

    Kann er und tut er:
    error: reference to local variable ‘reversed’ returned [-Werror=return-local-addr]|

    Wenn nicht, überprüfe deine Warnungseinstellungen (mit -Wall -Wextra und am besten auch mit -Werror kompilieren).



  • HarteWare schrieb:

    Wobei ich ganz provokant sagen muss, funktioniert hats trotzdem

    Das kann nicht funktioniert haben, da die lokale Variable hier ja kein dummer int ist, der irgendwo noch rumliegt bis er zufällig überschrieben wird, sondern einen Destruktor hat. Du kannst also maximal auf einen leeren Vektor zugegriffen haben.

    (Achso, das meintest du mit "funktioniert"?)

    und warnen tut mich der Compiler auch nicht, wobei der sowas mit Leichtigkeit erkennen könnte

    Ja, sollte er eigentlich. Sicher, dass du eine ausreichend hohe Warnungsstufe aktiviert hast?



  • Ok, ich habe nochmals nachgeschaut, da hatte ich das schon verbessert, und wenn ich wieder die Referenz hinmache und versuche die Funktion zu nutzen, dann gibts sogar nen Error.

    Habe also ganz umsonst eine weitere Diskussion angeheizt, mein Fehler, sorry.. 🙄

    lg
    HarteWare


Anmelden zum Antworten