Wozu std::array?



  • Ich finde das Ding nervig. Ist ja schoen und gut, wenns nun kopierbar ist. Aber wie oft will man tatsaechlich ein Array kopieren, anstatt per Referenz herumreichen? Iteratoren bekomme ich, wie bei allen anderen Containern auch, mit freien begin()/end().

    Fuer std::array brauch ich ein #include, hab mehr zu tippen (T[N] vs. std::array<T, N>), und ich muss die Groesse immer explizit hinschreiben.

    Fuer mich den Aufwand nicht wert.

    Gruesse,
    Der Kellerautomat



  • Kellerautomat schrieb:

    Ich finde das Ding nervig.

    Niemand zwingt dich es zu nutzen, ich finde die Vorteile wesentlich wichtiger als die Nachteile (unter Anderem das man bei übergaben nicht die Größe mitführen muss etc.).


  • Mod

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1479.html

    Ja, ein paar dieser Gründe sind mit C++11 weggefallen. Aber mindestens die Debugmöglichkeiten und size() sind es mMn schon Wert.



  • std::array ist super. Ich brauche nie mehr Arrays, weil sie in sämtlichen Punkten unterlegen sind. Minimal kleinerer Schreibaufwand ist für mich kein relevantes Kriterium, erst recht nicht in Anbetracht der Nachteile.

    Vorteile von std::array :

    • Wertsemantik
      Du hast ein eigentliches Objekt, das sich auch so verhält und nicht aus Traditionsgründen etliche Sonderregeln bereithält. Kopieren ist alleine schon daher nützlich, weil du std::array -Objekte von Funktionen zurückgeben kannst.
    • Kein array-to-pointer decay
      Die implizite Konvertierung zu Zeigern ist eine unnötige Fehlerquelle. So selten wie man das braucht, ist eine aussagekräftige Methode viel angebrachter.
    • STL-Interface
      Du hast nicht nur begin() und end() , sondern auch size() und andere nützliche Methoden.
    • Sicherheit
      Jede vernünftige std::array -Implementierung prüft im Debug-Modus Indizes und eventuell sogar Iteratoren. Alleine das wäre Grund genug es zu nutzen, zumindest falls du schon mal länger wegen solchen Fehlern debuggen musstest.


  • asc schrieb:

    Niemand zwingt dich es zu nutzen, ich finde die Vorteile wesentlich wichtiger als die Nachteile (unter Anderem das man bei übergaben nicht die Größe mitführen muss etc.).

    std::array hat einen Template-Parameter fuer die Groesse. Irgendwo musst du diese also mitfuehren, da sie zum Typ gehoert.

    Moeglichkeiten:

    template <size_t N>
    void foo(array<int, N> const&);
    
    void foo(array<int, CONSTANT> const&);
    

    So viel besser finde ich das nun auch nicht als:

    void foo(int const* data, size_t size);
    

    Und dieses Interface funktioniert dann auch in C.



  • Kellerautomat schrieb:

    Ich finde das Ding nervig.

    Ganz objektiv gesehen hat es folgende Vorteile

    • Bound-Checks mit at
    • Bound-Check bei operator[] im Debug-Modus
    • Unterstützt tuple-Funktionen
    • Kopierbar, Swapbar, ...
    • Alles finden es cool, weil einfach verständliches C++11-Feature und einfache Syntax

    Dass es size hat ist kein Argument, weil eine freie size-Funktion kann das auch für Arrays machen.

    Ich denke, der letzte Punkt ist ausschlaggebend. Die anderen Punkte sind irgendwie ... sinnfrei. Wer es wirklich kopieren will, ist mit std::tuple besser aufgehoben, das kann auch EBO.


  • Mod

    Kellerautomat schrieb:

    asc schrieb:

    Niemand zwingt dich es zu nutzen, ich finde die Vorteile wesentlich wichtiger als die Nachteile (unter Anderem das man bei übergaben nicht die Größe mitführen muss etc.).

    std::array hat einen Template-Parameter fuer die Groesse. Irgendwo musst du diese also mitfuehren, da sie zum Typ gehoert.

    Moeglichkeiten:

    template <size_t N>
    void foo(array<int, N> const&);
    
    void foo(array<int, CONSTANT> const&);
    

    So viel besser finde ich das nun auch nicht als:

    void foo(int const* data, size_t size);
    

    Und dieses Interface funktioniert dann auch in C.

    So macht man das nicht in C++. Da nutzt man Iteratoren. Wenn du mit Gewalt ein C-Interface nachbauen möchtest, dann ist klar, dass das nicht schön wird.



  • SeppJ schrieb:

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1479.html

    Ja, ein paar dieser Gründe sind mit C++11 weggefallen. Aber mindestens die Debugmöglichkeiten und size() sind es mMn schon Wert.

    Wie bereits gesagt wurde, kann man auch size() als freie Funktion bauen. Aber selbst

    sizeof x / sizeof *x
    

    finde ich gar nicht mal schlimm, wenn man es nur einmal braucht.

    Die "Debugmoeglichkeiten" habe ich lustigerweise noch nie vermisst bei rohen Arrays. Ich bin es mittlerweile schon gewohnt, wegen der folgenden Aussage als Troll bezeichnet zu werden, aber ich kann mich tatsaechlich nicht erinnern, wann ich das letze mal ueber Arraygrenzen hinause versucht habe zu schreiben. Muss wohl schon einige Jahre her sein.

    Nexus schrieb:

    std::array ist super. Ich brauche nie mehr Arrays, weil sie in sämtlichen Punkten unterlegen sind. Minimal kleinerer Schreibaufwand ist für mich kein relevantes Kriterium, erst recht nicht in Anbetracht der Nachteile.

    Niemand benutzt gerne Dinge, die umstaendlich sind. "Umstaendlich" liegt nur im Auge des Betrachters. Ich finde einen zusaetzlichen Include und die ganze zusaetzlichen zeichen umstaendlich.

    Nexus schrieb:

    • Wertsemantik
      Du hast ein eigentliches Objekt, das sich auch so verhält und nicht aus Traditionsgründen etliche Sonderregeln bereithält. Kopieren ist alleine schon daher nützlich, weil du std::array -Objekte von Funktionen zurückgeben kannst.

    Daher meine Frage: Wie oft will man sowas wirklich? Ich benutze Arrays hauptsaechlich fuer statische Daten, die will ich gar nicht kopieren. Was macht ihr denn mit Arrays?

    Nexus schrieb:

    • Kein array-to-pointer decay
      Die implizite Konvertierung zu Zeigern ist eine unnötige Fehlerquelle. So selten wie man das braucht, ist eine aussagekräftige Methode viel angebrachter.

    array-to-pointer decay finde ich praktisch. Zwar nicht unbedingt optimal geloest (eine Art .ptr wie in D faende ich da besser), aber praktisch. Wieso ist das eine Fehlerquelle?

    Nexus schrieb:

    • STL-Interface
      Du hast nicht nur begin() und end() , sondern auch size() und andere nützliche Methoden.

    Kann, wie schon mal gesagt, durch freie Funktionen ersetzt werden.

    Nexus schrieb:

    • Sicherheit
      Jede vernünftige std::array -Implementierung prüft im Debug-Modus Indizes und eventuell sogar Iteratoren. Alleine das wäre Grund genug es zu nutzen, zumindest falls du schon mal länger wegen solchen Fehlern debuggen musstest.

    Diese Erfahrung habe ich (leider?) noch nicht gemacht.

    vieltipper schrieb:

    Ich denke, der letzte Punkt ist ausschlaggebend. Die anderen Punkte sind irgendwie ... sinnfrei. Wer es wirklich kopieren will, ist mit std::tuple besser aufgehoben, das kann auch EBO.

    Ja, da hast du wohl recht. Sieht cool aus und ist anfaengerfreundlich, daher wirds verwendet wo moeglich.
    Wie du jetzt aber auf std::tuple kommst, ist mir nicht klar. std::tuple hat seine eigenen Probleme. IMO gehoert dafuer eine Loesung in die Sprache, aber dafuer ist es in C++ wohl schon zu spaet.



  • SeppJ schrieb:

    So macht man das nicht in C++. Da nutzt man Iteratoren. Wenn du mit Gewalt ein C-Interface nachbauen möchtest, dann ist klar, dass das nicht schön wird.

    Dass man das mit Iteratoren macht, ist schon klar. Da haben rohe Arrays aber auch keine Nachteile, daher bin ich auf die Uebergabe eines Arrays eingegangen.



  • Kellerautomat schrieb:

    Wie bereits gesagt wurde, kann man auch size() als freie Funktion bauen.

    Natürlich kann man sich alles bauen. Der Punkt ist, dass dies mit std::array schon da ist.

    Wie viele Leute schreiben sich size() selbst? Genau niemand. Ist es nicht vorhanden, wird es nicht benutzt. Lieber nimmt man Nachteile in Kauf, " sizeof funktioniert ja auch".

    Kellerautomat schrieb:

    sizeof x / sizeof *x finde ich gar nicht mal schlimm, wenn man es nur einmal braucht.

    Alleine schon weil es ebenso mit Zeigern "funktioniert", ist es gefährlich.

    Kellerautomat schrieb:

    Die "Debugmoeglichkeiten" habe ich lustigerweise noch nie vermisst bei rohen Arrays. Ich bin es mittlerweile schon gewohnt, wegen der folgenden Aussage als Troll bezeichnet zu werden, aber ich kann mich tatsaechlich nicht erinnern, wann ich das letze mal ueber Arraygrenzen hinause versucht habe zu schreiben. Muss wohl schon einige Jahre her sein.

    Ja, solche Fehler passieren fast nie. Falls sie aber doch einmal passieren, ist man unheimlich froh, solche Sicherheitsmechanismen zu haben.

    Kellerautomat schrieb:

    Niemand benutzt gerne Dinge, die umstaendlich sind. "Umstaendlich" liegt nur im Auge des Betrachters. Ich finde einen zusaetzlichen Include und die ganze zusaetzlichen zeichen umstaendlich.

    Ja, man muss Prioritäten setzen. Die Vor- und Nachteile von std::array stehen aber in keinem Verhältnis zu einander.

    Kellerautomat schrieb:

    Daher meine Frage: Wie oft will man sowas wirklich? Ich benutze Arrays hauptsaechlich fuer statische Daten, die will ich gar nicht kopieren. Was macht ihr denn mit Arrays?

    Wenn man ein Array komplexer initialisieren will, kann man sich dafür eine Funktion schreiben, die ein gefülltes std::array zurückgibt.

    Kellerautomat schrieb:

    array-to-pointer decay finde ich praktisch. Zwar nicht unbedingt optimal geloest (eine Art .ptr wie in D faende ich da besser), aber praktisch. Wieso ist das eine Fehlerquelle?

    Jede implizite Konvertierung ist eine potenzielle Fehlerquelle. In diesem Fall z.B., weil eine falsche Überladung aufgerufen werden könnte. Du hast sicher schon gesehen, dass Leute versucht haben, Arrays mittels cout << array auszugeben. Du hast weder einen Fehler zur Kompilier- noch zur Laufzeit, sondern einen Bug im Code. Mit std::array hätte sowas gar nicht erst kompiliert.

    Kellerautomat schrieb:

    Diese Erfahrung habe ich (leider?) noch nicht gemacht.

    Einmal reicht, und du hast eine Lektion fürs Leben 😉

    Kellerautomat schrieb:

    Dass man das mit Iteratoren macht, ist schon klar. Da haben rohe Arrays aber auch keine Nachteile, daher bin ich auf die Uebergabe eines Arrays eingegangen.

    Doch, haben sie. Erstens musst du den end() -Iterator komplizierter berechnen, zweitens hast du keine Checked Iterators.


Log in to reply