Zugriff auf std::vector-Element: .at() oder []?



  • Hallo Leute,

    ich habe mal eine kurze Frage zu std::vector. Wie greift ihr auf die Elemente zu?

    1. mit .at()
    2. Direktzugriff mit []
    3. über einen Iterator?

    1. ist zwar verhältnismäßig langsam, aber wirft im Fehlerfall eine Exception.
    2. schneller, aber keine Prüfung wenn über die Grenzen hinaus gelesen/geschrieben wird
    3. noch etwas schneller (äh... bin mir jetzt nicht sicher, ob ich direkt auf ein bestimmtes Element zugreifen kann)

    Gibt es da eine bestimmte Empfehlung, was man nutzen sollte?

    viele Grüße,
    SBond



  • Ich würde prompt .at() sagen. Denn wegen Geschwindigkeit, die man wohl nur in Spezialfällen bräuchte, würde ich auf die genannten Vorteile gegenüber [] nicht verzichten wollen.



  • lemon03 schrieb:

    Ich würde prompt .at() sagen. Denn wegen Geschwindigkeit, die man wohl nur in Spezialfällen bräuchte, würde ich auf die genannten Vorteile gegenüber [] nicht verzichten wollen.

    Ich würde prompt [] sagen. Denn ein wohlprogrammierter Algorithmus wird niemals auf nicht-existierende Elemente eines Vektors zugreifen. Boundary-Checkings sollte man nur dort durchführen, wo sie wirklich notwendig sind, z.B. bei User-Eingaben.

    Edit: Und im Debug-Modus wird sowieso in aller Regel ein assert fliegen, sobald man mit [] Boundaries überschreitet. Eine Exception sollte nie notwendig sein.



  • oh je... also macht es quasi jeder anders 😮



  • Ich schätze, das kommt auch auf den Kenntnisstand an. Jodocus wird wohl deutlich weiter sein als ich, wodurch auch weniger Fehler auftreten können bzw anderes rangegangen wird. Mir leuchtet seine Argumentation ein, ich bin aber immer froh, wenn ich sofort einschätzen kann, weshalb das Ding jetzt abstürzt.



  • @lemon03: operator[] macht ebenfalls Bounds Checking* aber nur im Debug-Modus. assert schreibt auch alle relevanten Informationen nach stderr*. Ferner gibt's ja auch noch Core Dumps...
    Daher glaube ich nicht, dass das Fehlerquelle-finden-Argument zieht.

    *: Bei libstdc++ zumindest; sollte aber für alle brauchbaren Stdlibs gelten.

    LG



  • Ok, alles klar. Danke für die Aufklärung.

    Zumindest sollte man aber auch hinweisen, das zB in Anfänger oder 'Beginner'-Code oft darauf hingewiesen wird, eben .at() zu verwenden. Ich denke, dies macht man nicht zum Spaß.

    Falls es wirklich nur ums Optimum geht, habe ich die Frage vielleicht falsch verstanden.



  • SBond schrieb:

    Gibt es da eine bestimmte Empfehlung, was man nutzen sollte?

    Iteratoren und Algorithmen (aus std, boost oder auch selbst geschrieben).



  • Ich verwende (wenn es sein muss) den [] -Operator. Wie bereits geschrieben kann man zu Debug-Zwecken die Range Checks aktivieren. Noch besser ist weder [] noch at() zu verwenden (natuerlich nicht immer moeglich).

    Drei Arten die Element eines Vektors aufzusummieren.

    1. Kann man machen:

    vector<int> vec { 7, 8, 2, 12 };                                                                                       
    
    for ( size_t i = 0; i < vec.size(); ++i )                                                                              
        sum += vec[i];                                                                                                     
    cout << "Sum = " << sum << '\n';
    

    2. Mit Range-Based for Loops siehts schon besser aus:

    vector<int> vec { 7, 8, 2, 12 };                                                                                       
    
    int sum = 0;                                                                                                        
    for ( auto x : vec )                                                                                                
        sum += x;
    

    3. Am besten gleich mit STL Algorithmen:

    vector<int> vec { 7, 8, 2, 12 }; 
    
    int sum = accumulate(vec.cbegin(), vec.cend(), 0);
    

    Meistens ist es nicht notwendig den [] -Operator zu verwenden, woduch man keine Out-of-Bounds Probleme hat.


  • Mod

    Seit C++17 bietet sich für gewöhnliche Summierungen eher std::reduce an. Die Performance spricht für sich.



  • nochmals danke für die zahlreichen antworten 😃


Anmelden zum Antworten