std::array
ist den C-Arrays weit überlegen. Und selbst wenn ich mit Legacy-Code zusammenarbeiten möchte, kann ich ihn einfach verwenden std::array::data()
. Gibt es einen Grund, warum ich jemals ein Array der alten Schule haben möchte?
std::array
ist den C-Arrays weit überlegen. Und selbst wenn ich mit Legacy-Code zusammenarbeiten möchte, kann ich ihn einfach verwenden std::array::data()
. Gibt es einen Grund, warum ich jemals ein Array der alten Schule haben möchte?
Antworten:
Sofern ich nichts verpasst habe (ich habe die letzten Änderungen im Standard nicht zu genau verfolgt), bleiben die meisten Verwendungen von Arrays im C-Stil bestehen. std::array
Erlaubt zwar eine statische Initialisierung, zählt jedoch die Initialisierer für Sie nicht. Und da die einzige wirkliche Verwendung von Arrays im C-Stil zuvor std::array
für statisch initialisierte Tabellen war, wie folgt:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
Verwenden der üblichen begin
und end
Vorlagenfunktionen (in C ++ 11 übernommen), um diese zu durchlaufen. Ohne jemals die Größe zu erwähnen, die der Compiler aus der Anzahl der Initialisierer ermittelt.
EDIT: Eine andere Sache, die ich vergessen habe: String-Literale sind immer noch Arrays im C-Stil; dh mit Typ char[]
. Ich glaube nicht, dass irgendjemand die Verwendung von String-Literalen ausschließen würde, nur weil wir dies getan haben std::array
.
const char[]
Nein, um es klar auszudrücken. Und in 30 Zeichen.
Natürlich benötigen Sie C-Arrays, um sie zu implementieren std::array
, aber das ist nicht wirklich ein Grund, warum ein Benutzer jemals C-Arrays haben möchte. Darüber hinaus ist no std::array
nicht weniger leistungsfähig als ein C-Array und bietet eine Option für einen grenzüberprüften Zugriff. Und schließlich ist es völlig vernünftig, dass ein C ++ - Programm von der Standardbibliothek abhängt - das ist der Punkt, an dem es Standard ist - und wenn Sie keinen Zugriff auf eine Standardbibliothek haben, ist Ihr Compiler nicht konform und die Die Frage ist mit "C ++" gekennzeichnet, nicht mit "C ++" und den Nicht-C ++ - Dingen, bei denen die Hälfte der Spezifikation fehlt, weil sie dies für unangemessen hielten. "
std::array
in einer freistehenden C ++ 11-Implementierung nicht implementiert werden konnte .
Die Verwendung mehrdimensionaler Arrays scheint mit C-Arrays einfacher zu sein als std::array
. Zum Beispiel,
char c_arr[5][6][7];
im Gegensatz zu
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
Aufgrund der automatischen Zerfallseigenschaft von C-Arrays wird c_arr[i]
im obigen Beispiel ein Zeiger zerfallen, und Sie müssen nur die verbleibenden Dimensionen als zwei weitere Parameter übergeben. Mein Punkt ist, dass c_arr
das Kopieren nicht teuer ist. Das cpp_arr[i]
Kopieren ist jedoch sehr kostspielig.
array
Funktion an eine Funktion übergeben, ohne Dimensionen zu verlieren. Wenn Sie es an eine Funktionsvorlage übergeben, kann diese Funktion sowohl die Dimension als auch die Größe jeder Dimension oder nur eine von beiden ableiten. Dies könnte für wissenschaftliche Vorlagenbibliotheken interessant sein, die hauptsächlich mit beliebigen Dimensionen arbeiten.
template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;
sollte eines dieser Probleme lösen.
c_arr
ist sehr teuer! Sie müssen den Code dafür selbst angeben. Der Zeiger, auf den er verfällt, entspricht eher einer Referenz als einer Kopie, und Sie können std::array
eine Referenz übergeben, wenn Sie dies wünschen.
std::size_t
statt sein int
? Entschuldigung für das Nitpicking, aber das würde es universell machen.
size_t
wenn Sie wollen, obwohl ich mir nicht vorstellen kann, dass es viele Szenarien gibt, in denen Arrays mit mehr als 4 Milliarden Zeilen oder Spalten erforderlich sind.
Wie Sumant sagte, sind mehrdimensionale Arrays mit eingebauten C-Arrays viel einfacher zu verwenden als mit std::array
.
Wenn verschachtelt, std::array
kann es sehr schwer zu lesen und unnötig ausführlich werden.
Beispielsweise:
std::array<std::array<int, 3>, 3> arr1;
verglichen mit
char c_arr[3][3];
Beachten Sie auch, dass begin()
, end()
und size()
alle Rückgabe sinnlose Werte , wenn Sie nisten std::array
.
Aus diesen Gründen habe ich meine eigene feste Größe mehrdimensionales Array - Container erstellt, array_2d
und array_3d
. Sie sind analog zu std::array
aber für mehrdimensionale Arrays mit 2 und 3 Dimensionen. Sie sind sicherer und haben keine schlechtere Leistung als integrierte mehrdimensionale Arrays. Ich habe keinen Container für mehrdimensionale Arrays mit Dimensionen größer als 3 eingefügt, da diese ungewöhnlich sind. In C ++ 0x könnte eine variable Vorlagenversion erstellt werden, die eine beliebige Anzahl von Dimensionen unterstützt.
Ein Beispiel für die zweidimensionale Variante:
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> my2darr = {{
{ 32.19, 47.29, 31.99, 19.11, 11.19},
{ 11.29, 22.49, 33.47, 17.29, 5.01 },
{ 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
Die vollständige Dokumentation finden Sie hier:
http://fsma.googlecode.com/files/fsma.html
Sie können die Bibliothek hier herunterladen:
arr[x][y]
Sie nicht sagen, ob arr
es sich um ein Array von Arrays, ein Array von Zeigern, einen Zeiger auf ein Array oder einen Zeiger auf einen Zeiger handelt. Alle Implementierungen sind abhängig von Ihren Anforderungen legitim. Und wahrscheinlich erfordern die meisten realen Anwendungsfälle für mehrdimensionale Arrays, dass die Größe zur Laufzeit bestimmt wird.
Die in C ++ verfügbaren Arrays im C-Stil sind tatsächlich viel weniger vielseitig als die echten C-Arrays. Der Unterschied besteht darin, dass Array-Typen in C Laufzeitgrößen haben können. Das Folgende ist gültiger C-Code, kann jedoch weder mit C ++ - Arrays im C-Stil noch mit den C ++ - array<>
Typen ausgedrückt werden:
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
In C ++ müssten Sie das temporäre Array auf dem Heap zuweisen:
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
Dies kann nicht erreicht werden std::array<>
, da bar
zur Kompilierungszeit nicht bekannt ist, dass entweder C-artige Arrays in C ++ oder von verwendet werden müssen std::vector<>
.
Während das erste Beispiel relativ leicht in C ++ ausgedrückt werden kann (obwohl dies erforderlich ist new[]
und delete[]
), kann Folgendes in C ++ nicht erreicht werden ohne std::vector<>
:
void smoothImage(int width, int height, int (*pixels)[width]) {
int (*copy)[width] = malloc(height*sizeof(*copy));
memcpy(copy, pixels, height*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y][x] = //compute smoothed value based on data around copy[y][x]
}
}
free(copy);
}
Der Punkt ist, dass die Zeiger auf die Zeilenarrays int (*)[width]
in C ++ keine Laufzeitbreite verwenden können, was jeden Bildmanipulationscode in C ++ viel komplizierter macht als in C. Eine typische C ++ - Implementierung des Bildmanipulationsbeispiels würde folgendermaßen aussehen:
void smoothImage(int width, int height, int* pixels) {
int* copy = new int[height*width];
memcpy(copy, pixels, height*width*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
}
}
delete[] copy;
}
Dieser Code führt genau die gleichen Berechnungen wie der obige C-Code durch, muss jedoch die Indexberechnung von Hand durchführen, wo immer die Indizes verwendet werden . Für den 2D-Fall ist dies immer noch möglich (obwohl es viele Möglichkeiten gibt, die Indexberechnung falsch zu machen). Im 3D-Fall wird es allerdings sehr unangenehm.
Ich schreibe gerne Code in C ++. Aber wenn ich mehrdimensionale Daten bearbeiten muss, frage ich mich wirklich, ob ich diesen Teil des Codes nach C verschieben soll.
gcc
zum Beispiel) seine VLA-Funktionen implementieren . C11 hat eine Menge interessanter Dinge optional gemacht, und ich glaube nicht, dass das daran liegt, dass sie die Funktion verbieten wollen. Ich neige dazu, es als Zeichen dafür zu sehen, dass sie die Stufe für das Schreiben eines vollständig standardkonformen Compilers senken wollten: VLAs sind ziemlich schwierig zu implementieren, und viel Code kann darauf verzichten, daher ist es für einen neuen Compiler auf einem neuen sinnvoll Plattform, um VLAs nicht sofort implementieren zu müssen.
Vielleicht ist das std::array
nicht langsam. Aber ich habe ein Benchmarking mit einfachem Speichern durchgeführt und aus dem std :: array gelesen. Siehe die folgenden Benchmark-Ergebnisse (auf W8.1, VS2013 Update 4):
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
Laut den negativen Markierungen befindet sich der von mir verwendete Code im Pastebin ( Link )
Der Benchmark-Klassencode ist hier ;
Ich weiß nicht viel über Benchmarking ... Mein Code ist möglicherweise fehlerhaft
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}
jetzt in etwas verwandeln . Sie müssen wirklich durch die Reifen springen, um sicherzustellen, dass der Code, den Sie messen, der Code ist, den Sie messen möchten.
std::array
std::array
weniger performant als ein C-Array sein wird.
at()
, es ist nicht in operator[]
, genau wie std::vector
. Es gibt keine Leistungseinbußen oder Aufblähungen des Codes std::array
. Der Compiler wurde entwickelt, um solche Dinge zu optimieren. Und natürlich ist das Hinzufügen der aktivierten Funktion ein hervorragendes Debug-Tool und ein großer Vorteil. @ Lou Franco: Der gesamte C ++ - Code hängt möglicherweise von der Standardbibliothek ab - dafür ist er genau das Richtige. @Earlz: Wenn Sie keine STL zur Verfügung haben, dann ist es nicht C ++, und das ist das Ende davon.
std::array
größer ist als die entsprechende C-Array-Verwendung.