¿Inicialización predeterminada de matrices de miembros de C++?

5 minutos de lectura

Esta es una pregunta simple, pero parece que no puedo encontrar una respuesta definitiva.

Si tenemos la siguiente clase:

class Test
{
...
  char testArray[10];

...
}; 

Cuando creamos una instancia de Test, ¿cuál es el valor predeterminado de testArray?[1]?

Si fuera una matriz local, no se inicializaría.
Si fuera una matriz estática, se inicializaría en 0.

¿Qué hace cuando la matriz es un miembro de la clase?

  • Depende del resto de la definición de la clase, incluida la definición de cualquier constructor y, potencialmente, de cómo se instancia la instancia de la clase. Muestra más código.

    –CB Bailey

    13/10/2011 a las 20:55


  • ¿Qué quiere decir con “miembro de la clase”? El ejemplo testArray ha mostrado, en C++, pertenece a instancias, no a la clase. Para que pertenezca a la clase necesitarías hacerlo staticy definirlo en otro lugar.

    – Karl Knechtel

    13/10/2011 a las 21:03

  • @KarlKnechtel: Luciano está usando el término correctamente. testArray es un miembro de datos no estático de la clase. “Los miembros de una clase son miembros de datos, funciones de miembros (9.3), tipos anidados y enumeradores. Los miembros de datos y las funciones de miembros son estáticos o no estáticos; consulte 9.4”.

    – Ben Voigt

    13/10/2011 a las 21:06

  • Charles: suponga que el constructor de Test no asigna valores a testArray.

    – Luciano

    13/10/2011 a las 21:07

  • @CharlesBailey: No realmente. Si un constructor proporciona un inicializador, entonces no sería inicializado por defectosino “¿Qué constituye inicialización por defecto para un miembro de la matriz?” sigue siendo una pregunta válida.

    – Ben Voigt

    13/10/2011 a las 21:07

Avatar de usuario de Ben Voigt
ben voigt

De la norma, apartado 8.5 [dcl.init]:

Para inicializar por defecto un objeto de tipo T medio:

  • si T es un tipo de clase (posiblemente cv-calificado) (Cláusula 9), el constructor predeterminado para T se llama (y la inicialización está mal formada si T no tiene un constructor predeterminado accesible);

  • si T es un tipo de matriz, cada elemento es inicializado por defecto;

  • de lo contrario, no se realiza ninguna inicialización.

también la sección 12.6.2 [class.base.init]:

En un constructor que no delega, si un miembro de datos no estático o una clase base determinada no está designada por un mem-inicializador-id (incluido el caso en que no haya lista de inicializadores de mem porque el constructor no tiene ctor-inicializador) y la entidad no es una clase base virtual de una clase abstracta (10.4), entonces

  • si la entidad es un miembro de datos no estáticos que tiene un inicializador de llave o igualla entidad se inicializa como se especifica en 8.5;
  • de lo contrario, si la entidad es un miembro variante (9.5), no se realiza la inicialización;
  • de lo contrario, la entidad es inicializado por defecto (8.5).

Entonces, debido a que el tipo de elemento es charcuando cada elemento es inicializado por defecto, no se realiza ninguna inicialización. Los contenidos se dejan con valores arbitrarios.

A menos, por supuesto, que sea miembro de una instancia de la clase y la instancia tenga una duración de almacenamiento estática. Entonces toda la instancia es inicializado a ceromiembros de la matriz y todo, antes de que comience la ejecución.

  • Entonces, si entiendo correctamente, el valor no se inicializará por defecto a menos que la instancia de la clase Test sea una instancia estática.

    – Luciano

    13/10/2011 a las 21:15

  • @Luciano: No, se inicializará por defecto si el constructor no especifica un inicializador para él (incluido el constructor implícito que permite la inicialización de agregados). Inicialización predeterminada de un char[] es un no-op. Si la instancia tiene una duración de almacenamiento estático, entonces había ceros antes, por lo que después de no operar, sigue siendo cero. En otros casos, lo que quede en la memoria determinará el valor.

    – Ben Voigt

    13/10/2011 a las 21:23


  • @BenVoigt ¿Se puede aplicar esta regla a una matriz estática? si definimos un int local, tendrá un valor aleatorio, pero si definimos un int estático, se establecerá en 0. ¿La matriz estática tiene el mismo comportamiento? se puede encontrar una discusión aquí: stackoverflow.com/q/2091499/440403

    – camino

    7 junio 2018 a las 14:10


  • @camino: Un local sin inicialización no es un valor “aleatorio”, es un valor indeterminado. La diferencia es importante y realmente estropeó el software de criptografía: research.swtch.com/openssl Los elementos de las matrices estáticas tienen una duración de almacenamiento estática y, por lo tanto, se llenan con ceros. Estar dentro de una matriz u otro agregado no hace ninguna diferencia.

    – Ben Voigt

    7 junio 2018 a las 14:25

  • @BenVoigtq Ya veo, ¡muchas gracias!

    – camino

    7 de junio de 2018 a las 14:28

Depende de muchos factores que olvidaste mencionar.

Si tu Test no tiene un constructor definido por el usuario o su constructor definido por el usuario no hace ningún esfuerzo por inicializar la matriz, y usted declara el objeto de tipo Test como

Test test; // no initializer supplied

entonces se comportará exactamente de la misma manera que describiste anteriormente. Para un objeto automático (local), el contenido de la matriz seguirá siendo impredecible. Para un objeto estático, se garantiza que el contenido es cero.

Si su clase tiene un constructor definido por el usuario, entonces todo dependerá de lo que haga el constructor. Nuevamente, tenga en cuenta que los objetos estáticos siempre se inicializan en cero antes de que cualquier constructor tenga la oportunidad de hacer algo.

Si su clase es un agregado, entonces el contenido podría depender del inicializador agregado que proporcionó en la declaración del objeto. Por ejemplo

Test test = {};

inicializará a cero la matriz incluso para un objeto automático (local).

  • Y si testArray() se llama dentro de la lista de inicialización del constructor, cada elemento de la matriz se inicializará con un valor (lo que significa que se establecerá en 0 para este caso particular)

    – K-ballo

    13/10/2011 a las 21:01

  • Ninguno de estos casos es una inicialización predeterminada. La pregunta pregunta qué sucede durante la inicialización predeterminada.

    – Ben Voigt

    13/10/2011 a las 21:09

  • @Ben Voigt: Aparentemente, la pregunta hace un mal uso del término “inicialización predeterminada”. Ocurre con bastante frecuencia cuando las personas asumen que si no hacen nada en absoluto, se produce algún tipo de “inicialización predeterminada”. En realidad, la “inicialización predeterminada” en C++ significa algo diferente. Es por eso que no restrinjo la respuesta a “inicialización predeterminada”.

    – AnT apoya a Rusia

    13/10/2011 a las 21:34

Creo que si no lo inicializa cuando lo declara, puede configurarse en cualquier cosa. A veces es una dirección o un valor de aspecto aleatorio.

La mejor práctica es inicializar después de declarar.

¿Ha sido útil esta solución?