C ++ Hinweise: Die Array-Initialisierung hat eine schöne Liste über die Initialisierung von Arrays. Ich habe ein
int array[100] = {-1};
Erwarten Sie, dass es voll mit -1 ist, aber es ist nicht so, nur der erste Wert ist und der Rest sind 0 mit zufälligen Werten gemischt.
Der Code
int array[100] = {0};
funktioniert einwandfrei und setzt jedes Element auf 0.
Was fehlt mir hier? Kann man es nicht initialisieren, wenn der Wert nicht Null ist?
Und 2: Ist die Standardinitialisierung (wie oben) schneller als die übliche Schleife durch das gesamte Array und weist einen Wert zu oder macht sie dasselbe?
{0}
ist kein Sonderfall für Strukturen oder Arrays. Die Regel ist, dass Elemente ohne Initialisierer wie0
für einen Initialisierer initialisiert werden. Wenn verschachtelte Aggregate vorhanden sind (z. B.struct x array[100]
), werden Initialisierer in der Reihenfolge "Zeilen-Haupt" auf die Nicht-Aggregate angewendet. Klammern können dabei optional weggelassen werden.struct x array[100] = { 0 }
ist gültig in C; und gültig in C ++, solange das erste Mitglied von als Initialisiererstruct X
akzeptiert0
.{ 0 }
ist in C nicht besonders, aber es ist viel schwieriger, einen Datentyp zu definieren, der damit nicht initialisiert werden kann, da es keine Konstruktoren gibt und daher nicht verhindert werden kann0
, implizit konvertiert und etwas zugewiesen zu werden .Antworten:
Verwenden Sie die von Ihnen verwendete Syntax.
sagt "setze das erste Element auf
-1
und den Rest auf0
", da alle ausgelassenen Elemente auf gesetzt sind0
.In C ++ können Sie zum Festlegen aller
-1
Optionen Folgendes verwenden :std::fill_n
(from<algorithm>
):In tragbarem C müssen Sie Ihre eigene Schleife rollen. Es gibt Compiler-Erweiterungen oder Sie können sich auf das implementierungsdefinierte Verhalten als Verknüpfung verlassen, wenn dies akzeptabel ist.
quelle
#include <algorithm>
ist der richtige Header,<vector>
kann ihn indirekt enthalten oder nicht, was von Ihrer Implementierung abhängen würde.int
s generieren und in den Initialisierer des Arrays erweitern.fill_n
zum Füllen eines gesamten 2D-Arrays zu verwenden. Sie müssen eine Dimension durchlaufen, während Sie die andere ausfüllen.std::fill_n
ist keine Initialisierung.Es gibt eine Erweiterung des gcc-Compilers, die die Syntax zulässt:
Dies würde alle Elemente auf -1 setzen.
Dies ist bekannt als „Designated Initializers“ sieht hier für weitere Informationen.
Beachten Sie, dass dies für den gcc c ++ - Compiler nicht implementiert ist.
quelle
Die Seite, auf die Sie verlinkt haben, gab bereits die Antwort auf den ersten Teil:
Es gibt keine integrierte Möglichkeit, das gesamte Array auf einen Wert ungleich Null zu initialisieren.
Was schneller ist, gilt die übliche Regel: "Die Methode, die dem Compiler die größte Freiheit gibt, ist wahrscheinlich schneller."
sagt dem Compiler einfach "setze diese 100 Ints auf Null", was der Compiler frei optimieren kann.
ist viel spezifischer. Es weist den Compiler an, eine Iterationsvariable zu erstellen
i
, gibt die Reihenfolge an, in der die Elemente initialisiert werden sollen, und so weiter. Natürlich wird der Compiler dies wahrscheinlich optimieren, aber der Punkt ist, dass Sie hier das Problem überbestimmen und den Compiler dazu zwingen, härter zu arbeiten, um zum gleichen Ergebnis zu gelangen.Wenn Sie das Array auf einen Wert ungleich Null setzen möchten, sollten Sie (zumindest in C ++) Folgendes verwenden
std::fill
:Auch hier können Sie dasselbe mit einem Array tun, dies ist jedoch präziser und gibt dem Compiler mehr Freiheit. Sie sagen nur, dass Sie möchten, dass das gesamte Array mit dem Wert 42 gefüllt wird. Sie sagen nichts darüber, in welcher Reihenfolge es ausgeführt werden soll oder sonst etwas.
quelle
C ++ 11 hat eine andere (unvollständige) Option:
quelle
std::fill(begin(a), end(a), -1)
Mit {} weisen Sie die Elemente so zu, wie sie deklariert sind. Der Rest wird mit 0 initialisiert.
Wenn es keine
= {}
Initialisierung gibt, ist der Inhalt undefiniert.quelle
Die Seite, die Sie verlinkt haben, gibt an
Geschwindigkeitsproblem: Bei so kleinen Arrays wären Unterschiede vernachlässigbar. Wenn Sie mit großen Arrays arbeiten und die Geschwindigkeit viel wichtiger als die Größe ist, können Sie ein const-Array mit den Standardwerten (zur Kompilierungszeit initialisiert) und diese dann
memcpy
in das modifizierbare Array einfügen.quelle
Eine andere Möglichkeit, das Array auf einen gemeinsamen Wert zu initialisieren, besteht darin, die Liste der Elemente in einer Reihe von Definitionen zu generieren:
Das Initialisieren eines Arrays auf einen gemeinsamen Wert ist einfach:
Hinweis: DUPx wurde eingeführt, um die Makrosubstitution in Parametern für DUP zu ermöglichen
quelle
Für den Fall eines Arrays von Einzelbyte-Elementen können Sie memset verwenden, um alle Elemente auf denselben Wert zu setzen.
Es ist ein Beispiel hier .
quelle
Mit
std::array
können wir dies in C ++ 14 auf ziemlich einfache Weise tun. Dies ist nur in C ++ 11 möglich, jedoch etwas komplizierter.Unsere Schnittstelle hat eine Größe zur Kompilierungszeit und einen Standardwert.
Die dritte Funktion dient hauptsächlich der Bequemlichkeit, so dass der Benutzer kein
std::integral_constant<std::size_t, size>
Selbst konstruieren muss, da dies eine ziemlich wortreiche Konstruktion ist. Die eigentliche Arbeit erledigt eine der ersten beiden Funktionen.Die erste Überladung ist ziemlich einfach: Sie erstellt eine
std::array
Größe 0. Es ist kein Kopieren erforderlich, wir erstellen sie einfach.Die zweite Überlastung ist etwas kniffliger. Es leitet den Wert weiter, den es als Quelle erhalten hat, und erstellt auch eine Instanz von
make_index_sequence
und ruft nur eine andere Implementierungsfunktion auf. Wie sieht diese Funktion aus?Dadurch werden die ersten Argumente der Größe 1 erstellt, indem der übergebene Wert kopiert wird. Hier verwenden wir unsere variablen Parameterpaketindizes nur als Erweiterung. Es gibt Einträge der Größe 1 in diesem Paket (wie wir in der Konstruktion von angegeben haben
make_index_sequence
) und sie haben Werte von 0, 1, 2, 3, ..., Größe - 2. Die Werte sind uns jedoch egal ( Also haben wir es für ungültig erklärt, um alle Compiler-Warnungen zum Schweigen zu bringen. Die Erweiterung des Parameterpakets erweitert unseren Code auf etwa Folgendes (vorausgesetzt, Größe == 4):Wir verwenden diese Klammern, um sicherzustellen, dass die Erweiterung des Variadic Packs das
...
erweitert, was wir wollen, und um sicherzustellen, dass wir den Komma-Operator verwenden. Ohne die Klammern würde es so aussehen, als würden wir eine Reihe von Argumenten an unsere Array-Initialisierung übergeben, aber tatsächlich bewerten wir den Index, wandeln ihn in void um, ignorieren dieses void-Ergebnis und geben dann den Wert zurück, der in das Array kopiert wird .Das letzte Argument, auf das wir zurückgreifen
std::forward
, ist eine geringfügige Optimierung. Wenn jemand einen temporären std :: string übergibt und sagt "mache ein Array von 5 davon", möchten wir 4 Kopien und 1 Zug anstelle von 5 Kopien haben. Dasstd::forward
stellt sicher, dass wir dies tun.Der vollständige Code, einschließlich Header und einiger Komponententests:
quelle
non_copyable
Typ kann tatsächlich mit kopiert werdenoperator=
.non_copy_constructible
wäre ein genauerer Name für das Objekt. Da in diesem Code jedoch keine Zuordnung vorhanden ist, spielt dies für dieses Beispiel keine Rolle.1) Wenn Sie einen Initialisierer für eine Struktur oder ein Array wie dieses verwenden, werden die nicht angegebenen Werte im Wesentlichen standardmäßig erstellt. Bei einem primitiven Typ wie Ints bedeutet dies, dass sie auf Null gesetzt werden. Beachten Sie, dass dies rekursiv gilt: Sie können ein Array von Strukturen haben, die Arrays enthalten. Wenn Sie nur das erste Feld der ersten Struktur angeben, wird der Rest mit Nullen und Standardkonstruktoren initialisiert.
2) Der Compiler generiert wahrscheinlich Initialisierungscode, der mindestens so gut ist, wie Sie es von Hand tun könnten. Ich ziehe es vor, den Compiler nach Möglichkeit die Initialisierung für mich durchführen zu lassen.
quelle
In C ++ ist es auch möglich, Metaprogrammierung und verschiedene Vorlagen zu verwenden. Der folgende Beitrag zeigt, wie es geht: Erstellen Sie programmgesteuert statische Arrays zur Kompilierungszeit in C ++ .
quelle
In der C ++ - Programmiersprache V4 empfiehlt Stroustrup die Verwendung von Vektoren oder Valarrays gegenüber integrierten Arrays. Wenn Sie Valarrarys erstellen, können Sie sie beim Erstellen auf einen bestimmten Wert wie folgt einleiten:
So initialisieren Sie ein 7 Mitglieder langes Array mit "7777777".
Dies ist eine C ++ - Methode zum Implementieren der Antwort mithilfe einer C ++ - Datenstruktur anstelle eines "einfachen alten C" -Arrays.
Ich habe den Valarray als Versuch in meinem Code verwendet, C ++ 'isms v. C'isms zu verwenden ....
quelle
Sollte eine Standardfunktion sein, ist aber aus irgendeinem Grund weder in Standard C noch in C ++ enthalten ...
In Fortran können Sie Folgendes tun:
aber es hat keine vorzeichenlosen Nummern ...
Warum kann C / C ++ es nicht einfach implementieren? Ist es wirklich so schwer? Es ist so dumm, dies manuell schreiben zu müssen, um das gleiche Ergebnis zu erzielen ...
Was wäre, wenn es ein Array von 1.000,00 Bytes wäre? Ich müsste ein Skript schreiben, um es für mich zu schreiben, oder auf Hacks mit Assembly / etc. Zurückgreifen. Das ist schwachsinn.
Es ist perfekt portabel, es gibt keinen Grund dafür, nicht in der Sprache zu sein.
Hacken Sie es einfach wie folgt:
Eine Möglichkeit, es zu hacken, ist die Vorverarbeitung ... (Der folgende Code deckt keine Randfälle ab, sondern wurde geschrieben, um schnell zu demonstrieren, was getan werden kann.)
quelle
memset
, selbst mit dem "fest codierten" Array.