Pregunta

Cuando inicializamos una matriz como esta int a[5] = {0}, el compilador fabrica los 5 elementos 0. Eso es realmente bueno, Inicialización compacta y característica útil.

Pero me pregunto por qué el compilador no inicializa int a[5]={1} ¿similar? ¿Por qué no hace los 5 elementos 1? ¿Por qué el estándar no lo exige? ¿No sería una característica increíble? ¿No está faltando?

Además, si el número de elementos en el inicializador es menor que el tamaño de la matriz, entonces la compilación podría inicializar los elementos restantes con el último elemento en el inicializador. Medio, int a[5]={1,2,3} es equivalente a int a[5]={1,2,3,3,3}. Y de manera similar, int a[10]={1,2,3,0} es equivalente a int a[10]={1,2,3,0,0,0,0,0,0,0};.

¿No sería todo una característica increíble si el estándar lo exige? ¿O hay alguna buena razón para esta característica faltante?


Y hay algo llamado inicializador designado En C99, que se usa como:

Los inicializadores designados se pueden combinar con inicializadores regulares, como en el siguiente ejemplo:

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

En este ejemplo, un [0] se inicializa a 2, un1 se inicializa a 4, A [2] a A [7] se inicializan a 0, y A [9] se inicializa a 10.

Bastante interesante. Pero incluso esta característica no está en C ++.

¿Fue útil?

Solución

Personalmente, encuentro más "lógico" (es decir, simple) que tiene un inicializador predeterminado fijo en lugar de otra regla de repetir la última solo para matrices. Eso puede parecer "práctico" (es decir, útil) pero es más lógicamente complejo.

Dicho esto, sin embargo, creo que estás haciendo un grande Error al tratar de aplicar la lógica a un idioma como C ++.

C ++ es un lenguaje complejo cuyas reglas son el resultado de una larga historia de evolución, y su forma actual es el resultado del trabajo de muchas personas e incluso de comités formales (la última parte podría explicar cualquier cosa).

Un lenguaje como C ++ no puede ser inferido por la lógica, debe estudiarse como la historia. A menos que seas Hari Seldon Realmente no hay forma de que pueda inferir la historia usando un razonamiento lógico.

Hay lugares de C ++ en los que vas a sufrir mucho si intentas usar la lógica en lugar de estudiar. Sólo para nombrar unos pocos...

  • ¿Por qué el despacho predeterminado es estático (es decir? equivocado)?
  • ¿Por qué no hay palabra clave para el puntero nulo?
  • ¿Por qué la diferencia de dos sin firmar está sin firmar?
  • ¿Por qué una suma entre un firmado y un sin firmar no está firmado?
  • Si no firme significa "elemento de Z_ {2^n}"Entonces, ¿por qué los tamaños no están firmados?
  • Por qué std::string s; s=3.141592654; ¿Es perfectamente válido C ++?
  • Por qué en C ++ 0x i = i++ + 1; es un comportamiento indefinido y i = ++i + 1; ¿es válida?
  • Por qué double x=3.14; int y(int(x)); no significa y serán 3?

Otros consejos

¿Por qué no hace los 5 elementos 1?

Porque estás malinterpretando lo que {} medio. (En realidad, en C ++ la mejor manera de hacer esto es {} más bien que {0}). La sintaxis {0} No significa que desee todos los elementos en el conjunto agregado en cero. Más bien, dice que desea un agregado con el primer elemento cero asignado a la variable indicada (que puede ser una matriz o un tipo de clase en C ++). Debido a que el agregado generalmente tiene más campos que ese valor cero, los elementos restantes en el agregado son construido por defecto. El valor predeterminado de un tipo Builtin o POD es establecer todos los campos en cero, por lo que efectivamente ha establecido todo el agregado en cero.

En cuanto a por qué específicamente, considere lo siguiente. Según el estándar actual, ninguna de las afirmaciones a continuación fallará:

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);
}

¿Qué esperarías el valor de field3 ¿Estar en su cambio estándar propuesto? Incluso si lo define como el último elemento en el inicializador agregado como ha mostrado anteriormente, eso romperá la compatibilidad con el código existente que supone que el resto de los elementos están construidos por defecto.


EDITAR: Acabo de darme cuenta de que su pregunta se hace en términos de matrices, pero la respuesta es la misma con estructuras o matrices, por lo que realmente no importa.

Edit2: Para hacer esto más acorde con el estándar, las referencias a la clase/estructura se han reemplazado con "agregado" a continuación, que cubre las estructuras y los casos de matrices.

Si ellos pudo He hecho eso, pero no lo hicieron, y ya es demasiado tarde para cambiar ese comportamiento. Las decisiones detrás de C y C ++ se tomaron pensando al rendimiento y al minimalismo en casi todos los pasos, así que imagino que, si nada más, también entra en juego aquí.

Tal característica simplemente no me parece tan increíble. Es una pieza muy simple de azúcar sintáctica, y rara vez encuentro la necesidad de inicializar una matriz como esa a otra cosa que no sea 0 de todos modos.

Las bibliotecas típicas de tiempo de ejecución proporcionan una característica que facilita la inicialización de los datos a 0. En términos generales, esto se almacena en un sección en el ejecutable, organizado por el compilador y el enlazador. Al inicio del programa, el código de inicio de tiempo de ejecución usa algo como memset() Para borrar todos los datos inicializados a 0. Esto significa que los bytes cero no tienen que almacenarse dentro del ejecutable en sí.

Lo contrario es que si inicializa datos a algo otro que Cero, entonces los bytes para esos datos deben almacenarse en el ejecutable en sí, ya que el inicial del inicial solo se inicializa a cero.

Por lo tanto, si tuviera que declarar una gran variedad de char (¿digamos un megabyte?) Y lo inicializa con, digamos, {0}, entonces no habría bytes almacenados en el ejecutable para esa matriz. Por otro lado, si lo inicializara con {1} Bajo tu esquema, un megabyte de 1 Bytes tendría que almacenarse en el ejecutable en sí. Al cambiar un carácter en la lista de iniciales, el tamaño del ejecutable aumenta por un megabyte.

Creo que tal esquema violaría el Principio de menor sorpresa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top