std :: array vs array leistung

83

Wenn ich ein sehr einfaches Array wie erstellen möchte

int myArray[3] = {1,2,3};

Soll ich std::arraystattdessen verwenden?

std::array<int, 3> a = {{1, 2, 3}};

Was sind die Vorteile der Verwendung von std :: array gegenüber den üblichen? Ist es performanter? Einfacher zu handhaben für das Kopieren / Zugreifen?

Arcyno
quelle
2
Das Definieren eines mehrdimensionalen Arrays mit std :: wird schwierig sein
goGud
15
@goGud: Nicht schwer, nur ausführlicher.
Mike Seymour
1
Zeigerzerfall, Referenzieren usw. Viele Dinge sind an C-Arrays seltsam. Der Iterator kann ein Zeiger im Fall von c-Arrays sein und for (auto i = ++std::begin(myArray); . . . kann nicht einmal kompiliert werden (es scheint, dass Temporäre des fundamentalen Typs nicht veränderbar sind, zumindest nicht mit Clang 6)
Patrick Fromberg
Die Initialisierung unterscheidet sich auch magisch: struct Direction { int32_t dw; int32_t dh; };und static const Direction DIRECTIONS[DIRECTIONS_COUNT] { { -1, 1}, {0,1}, {1,1} , { 1, 0 }, {1,-1}, {0,-1} , {-1,-1}, {-1,0} };kompiliert. Wenn Sie jedoch zu einer std::array<Direction,DIRECTIONS_COUNT>Liste mit derselben Initialisierer wechseln , wird plötzlich der Fehler "Zu viele Initialisierer" angezeigt. (VS 2019 Community mit Sprache = C ++ 17)
BitTickler
Warum die doppelten Klammern in der std::arrayInitialisierung?
März 2377

Antworten:

100

Was sind die Vorteile der Verwendung std::arraygegenüber den üblichen?

Es hat eine benutzerfreundliche Wertesemantik, so dass es nach Wert an Funktionen übergeben oder von diesen zurückgegeben werden kann. Die Benutzeroberfläche erleichtert das Ermitteln der Größe und die Verwendung mit iteratorbasierten Algorithmen im STL-Stil.

Ist es performanter?

Es sollte genau das gleiche sein. Per Definition ist es ein einfaches Aggregat, das ein Array als einziges Mitglied enthält.

Einfacher zu handhaben für das Kopieren / Zugreifen?

Ja.

Mike Seymour
quelle
41

A std::arrayist ein sehr dünner Wrapper um ein Array im C-Stil, im Grunde definiert als

template<typename T, size_t N>
class array
{
public:
    T _data[N];
    T& operator[](size_t);
    const T& operator[](size_t) const;
    // other member functions and typedefs
};

Es ist ein Aggregat und ermöglicht es Ihnen, es fast wie einen grundlegenden Typ zu verwenden (dh Sie können Werte übergeben, zuweisen usw., während ein Standard-C-Array nicht direkt einem anderen Array zugewiesen oder kopiert werden kann). Sie sollten sich eine Standardimplementierung ansehen (von Ihrer bevorzugten IDE zur Definition springen oder direkt öffnen <array>). Sie ist ein Teil der C ++ - Standardbibliothek, der recht einfach zu lesen und zu verstehen ist.

vsoftco
quelle
24

std::array ist als Zero-Overhead-Wrapper für C-Arrays konzipiert, der den "normalen" Wert wie die Semantik der anderen C ++ - Container angibt.

Sie sollten keinen Unterschied in der Laufzeitleistung bemerken, während Sie die zusätzlichen Funktionen nutzen können.

Die Verwendung std::arrayvon int[]Arrays anstelle von Stilen ist eine gute Idee, wenn Sie C ++ 11 oder Boost zur Hand haben.

Baum mit Augen
quelle
10

Ist es performanter?

Es sollte genau das gleiche sein. Per Definition ist es ein einfaches Aggregat, das ein Array als einziges Mitglied enthält.

Die Situation scheint komplizierter zu sein, da std::arrayje nach Plattform nicht immer identischer Assembler-Code im Vergleich zu C-Array erzeugt wird.

Ich habe diese spezielle Situation auf Godbolt getestet :

#include <array>
void test(double* const C, const double* const A,
          const double* const B, const size_t size) {
  for (size_t i = 0; i < size; i++) {
    //double arr[2] = {0.e0};//
    std::array<double, 2> arr = {0.e0};//different to double arr[2] for some compiler
    for (size_t j = 0; j < size; j++) {
      arr[0] += A[i] * B[j];
      arr[1] += A[j] * B[i];
    }
    C[i] += arr[0];
    C[i] += arr[1];
  }
}

GCC und Clang erzeugen identischen Assemblycode sowohl für die C-Array-Version als auch für die std::arrayVersion.

MSVC und ICPC erzeugen jedoch für jede Array-Version unterschiedliche Assembler-Codes. (Ich habe ICPC19 mit -Ofastund getestet -Os; MSVC -Oxund -Os)

Ich habe keine Ahnung, warum dies der Fall ist (ich würde in der Tat ein genau identisches Verhalten von std :: array und c-array erwarten). Möglicherweise werden verschiedene Optimierungsstrategien angewendet.

Als kleines Extra: Es scheint einen Fehler in ICPC mit zu geben

#pragma simd 

zur Vektorisierung bei Verwendung des C-Arrays in bestimmten Situationen (der C-Array-Code erzeugt eine falsche Ausgabe; die std::arrayVersion funktioniert einwandfrei).

Leider habe ich noch kein minimales Arbeitsbeispiel dafür, da ich dieses Problem bei der Optimierung eines ziemlich komplizierten Codeteils entdeckt habe.

Ich werde einen Fehlerbericht an Intel senden, wenn ich sicher bin, dass ich nicht nur etwas über C-Array / std::arrayund falsch verstanden habe #pragma simd.

Henryk
quelle
1
kann als Compiler-Fehler angesehen werden?
OznOg
8

std::arrayhat Wertesemantik, während Raw-Arrays dies nicht tun. Dies bedeutet, dass Sie es kopieren std::arrayund wie einen primitiven Wert behandeln können. Sie können sie als Wert oder Referenz als Funktionsargumente empfangen und als Wert zurückgeben.

Wenn Sie niemals ein kopieren std::array, gibt es keinen Leistungsunterschied als bei einem Raw-Array. Wenn Sie Kopien erstellen std::arraymüssen, tun Sie das Richtige und sollten dennoch die gleiche Leistung erbringen.

b4hand
quelle