Frage

Wenn wir ein solches Array initialisieren int a[5] = {0}, Der Compiler macht alle 5 Elemente 0. Das ist wirklich gut, kompaktinitialisierung und nützliche Merkmale.

Aber ich frage mich, warum der Compiler nicht initialisiert int a[5]={1} ähnlich? Warum macht es nicht alle 5 Elemente 1? Warum ist der Standard nicht vorgeschrieben? Wäre es kein großartiges Feature? Fehlt es nicht?

Wenn die Anzahl der Elemente im Initialisierer geringer ist als die Größe des Arrays, kann das Kompilieren die verbleibenden Elemente mit dem letzten Element im Initialisierer initialisieren. Meint, int a[5]={1,2,3} ist äquivalent zu int a[5]={1,2,3,3,3}. Und ähnlich, int a[10]={1,2,3,0} ist äquivalent zu int a[10]={1,2,3,0,0,0,0,0,0,0};.

Wäre alles nicht eine großartige Funktion, wenn der Standard es vorschreibt? Oder gibt es gute Gründe für diese fehlende Funktion?


Und es gibt etwas, das genannt wird Bezeichner Initialisierer in C99, was verwendet wird wie:

Bezeichnete Initialisierer können wie im folgenden Beispiel mit regulären Initialisierern kombiniert werden:

int a[10] = {2, 4, [8]=9, 10}

In diesem Beispiel wird a [0] auf 2 initialisiert, a1 wird auf 4 initialisiert, a [2] bis a [7] werden auf 0 initialisiert und a [9] auf 10 initialisiert.

Ziemlich interessant. Aber auch diese Funktion ist nicht in C ++.

War es hilfreich?

Lösung

Ich persönlich finde persönlich mehr "logische" (dh einfach) mit einem festen Standard -Initialisierer anstelle einer anderen Regel der Wiederholung der letzten nur für Arrays. Das mag "praktisch" erscheinen (dh nützlich), aber es ist logisch komplexer.

Das heißt, aber ich denke, du machst eine groß Fehler beim Versuch, eine Logik auf eine Sprache wie C ++ anzuwenden.

C ++ ist eine komplexe Sprache, deren Regeln das Ergebnis einer langen Evolutionsgeschichte sind, und ihre aktuelle Form ist das Ergebnis der Arbeit vieler Menschen und sogar der formalen Ausschüsse (der letzte Teil allein könnte erklären irgendetwas).

Eine Sprache wie C ++ kann nicht durch Logik abgeleitet werden, sie muss wie Geschichte untersucht werden. Es sei denn, du bist Hari Seldon Es gibt wirklich keine Möglichkeit, die Geschichte mit logischem Denken zu schließen.

Es gibt Orte von C ++, an denen Sie viel leiden, wenn Sie versuchen, Logik zu verwenden, anstatt zu studieren. Nur um ein paar zu nennen...

  • Warum ist der Standard -Versand statisch (dh falsch)?
  • Warum gibt es kein Schlüsselwort für den Nullzeiger?
  • Warum ist der Unterschied von zwei nicht signiert nicht signiert?
  • Warum ist eine Summe zwischen einem unterzeichneten und einem nicht signierten nicht signiert?
  • Wenn nicht signiert bedeutet "Element von Z_ {2^n}"Warum sind dann Größen nicht signiert?
  • Warum std::string s; s=3.141592654; Ist C ++ perfekt gültig?
  • Warum in C ++ 0x i = i++ + 1; ist ein undefiniertes Verhalten und i = ++i + 1; ist gültig?
  • Warum double x=3.14; int y(int(x)); Das heißt nicht y wird 3 sein?

Andere Tipps

Warum macht es nicht alle 5 Elemente 1?

Weil du falsch versteht was {} meint. (Tatsächlich ist es in C ++ besser, dies zu tun {} statt {0}). Die Syntax {0} bedeutet nicht, dass Sie alle Elemente im Aggregat auf Null gesetzt haben. Es heißt vielmehr, dass Sie ein Aggregat mit dem ersten Element Null möchten, das der angegebenen Variablen zugeordnet ist (die entweder ein Array oder ein Klassentyp in C ++ sein kann). Da das Aggregat normalerweise mehr Felder als dieser einen Wert Null hat, sind die verbleibenden Elemente im Aggregat Standard konstruiert. Der Standardwert eines integrierten oder pod -Typs besteht darin, alle Felder auf Null zu setzen, sodass Sie das gesamte Aggregat effektiv auf Null gesetzt haben.

Warum sollten Sie sich speziell ansehen. Nach dem aktuellen Standard schlägt keine der folgenden Behauptungen fehl:

struct abc
{
    char field1;
    int field2;
    char field3;
};

int main()
{
    abc example = {'a', static_cast<int>('b')};
    //All three asserts pass
    assert(example.field1 == 'a');
    assert(example.field2 == static_cast<int>('b'));
    assert(example.field3 == '\0');

    int example2[3] = {static_cast<int>('a'), 42};
    assert(example2[0] == static_cast<int>('a'));
    assert(example2[1] == 42);
    assert(example2[2] == 0);
}

Was würden Sie den Wert von erwarten? field3 Um in Ihrer vorgeschlagenen Standardänderung zu sein? Selbst wenn Sie es als das letzte Element im Aggregat -Initialisierer definieren, wie oben gezeigt, wird dies die Kompatibilität mit vorhandenem Code durchbrechen, wodurch der Rest der Elemente standardmäßig konstruiert ist.


BEARBEITEN: Ich habe gerade erkannt, dass Ihre Frage in Bezug auf Arrays gestellt wird - aber die Antwort ist mit Strukturen oder Arrays gleich, so dass es wirklich keine Rolle spielt.

Edit2: Um dies im Einklang mit dem Standard zu gestalten, wurden Verweise auf Klassen/Struktur durch "Aggregat" nachstehend ersetzt, was die Strukturen und Arrays -Fälle abdeckt.

Ja sie könnte Ich habe das getan, aber sie haben es nicht getan, und es ist jetzt viel zu spät, um ein solches Verhalten zu ändern. Die Entscheidungen hinter C und C ++ wurden bei fast jedem Schritt mit Gedanken und Minimalismus getroffen. Ich stelle mir also vor, dass hier auch hier ins Spiel kommt.

Ein solches Feature trifft mich einfach nicht als so großartig. Es ist ein sehr einfaches Stück syntaktischer Zucker, und ich finde selten die Notwendigkeit, ein Array wie dieses sowieso auf etwas anderes als 0 zu initialisieren.

Typische Laufzeitbibliotheken bieten eine Funktion, mit der Daten auf 0 infiziert werden können. Im Allgemeinen wird dies in einem bestimmten Speicher gespeichert Sektion in der ausführbaren Datei, organisiert vom Compiler und Linker. Bei Program Startup verwendet der Startcode von Laufzeit so etwas wie memset() Um alle initialisierten Daten auf 0 zu löschen, bedeutet dies, dass die Null -Bytes nicht in der ausführbaren Datei selbst gespeichert werden müssen.

Das Gegenteil ist, dass, wenn Sie Daten zu etwas initialisieren außer Null, dann müssen die Bytes für diese Daten in der ausführbaren Datei selbst gespeichert werden, da der automatische Initialiser nur auf Null initialisiert.

Wenn Sie daher eine große Auswahl an deklarieren würden char (Sagen Sie einen Megabyte?) Und initialisieren Sie es mit beispielsweise, sagen Sie, {0}, Dann würden in der ausführbaren Datei für dieses Array keine Bytes gespeichert. Andererseits, wenn Sie es mit initialisieren würden {1} unter Ihrem Schema eine Megabyte von 1 Bytes müssten in der ausführbaren Datei selbst gespeichert werden. Durch Ändern eines Charakters in der Initialiserliste steigt die Größe der ausführbaren Datei um einen Megabyte.

Ich glaube, ein solches Schema würde gegen das verstoßen Prinzip der geringsten Überraschung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top