Miembro de matriz de inicialización cero en la lista de inicialización

5 minutos de lectura

Avatar de usuario de ValarDohaeris
ValarDohaeris

Tengo una clase con un miembro de matriz que me gustaría inicializar con todos ceros.

class X
{
private:
    int m_array[10];
};

Para una variable local, hay una forma sencilla de inicializar a cero (ver aquí):

int myArray[10] = {};

Además, el miembro de la clase m_array claramente debe inicializarse, ya que los ints de inicialización predeterminados solo dejarán basura aleatoria, como se explica aquí.

Sin embargo, puedo ver dos formas de hacer esto para una matriz de miembros:

Con paréntesis:

public:
    X()
    : m_array()
    {}

con llaves:

public:
    X()
    : m_array{}
    {}

¿Ambos son correctos? ¿Hay alguna diferencia entre los dos en C++ 11?

  • ¿Cómo estás probando? Al compilar con gcc -std=c++98recibo un mensaje “advertencia: las listas de inicializadores extendidas solo están disponibles con -std=c++11 o -std=gnu++11 [enabled by default]”, sin siquiera tener que agregar -pedantic.

    usuario743382

    9 dic 2014 a las 15:10

  • Acabo de comprobar rápidamente ideone.com con la opción C++ 4.8.1, no sé qué banderas usaron, así que eliminé mi reclamo.

    – ValarDohaeris

    9 de diciembre de 2014 a las 15:18

  • Visual Studio 2013 genera un mensaje de advertencia falso para la segunda opción: warning C4351: new behavior: elements of array 'X::m_array' will be default initialized

    – Chris Drew

    09/12/2014 a las 15:30

Inicializar cualquier miembro con () realiza la inicialización del valor.

Inicializar cualquier tipo de clase con un constructor predeterminado con {} realiza la inicialización del valor.

Inicializar cualquier otro tipo de agregado (incluidos los arreglos) con {} realiza la inicialización de la lista, y es equivalente a inicializar cada uno de los miembros del agregado con {}.

Inicializar cualquier tipo de referencia con {} construye un objeto temporal, que se inicializa desde {}y vincula la referencia a ese temporal.

Inicializar cualquier otro tipo con {} realiza la inicialización del valor.

Por lo tanto, para casi todos los tipos, la inicialización desde {} dará el mismo resultado que la inicialización del valor. No puede tener matrices de referencias, por lo que no pueden ser una excepción. Tú podría ser capaz de construir matrices de tipos de clases agregados sin un constructor predeterminado, pero los compiladores no están de acuerdo con las reglas exactas. Pero para volver a su pregunta, todos estos casos de esquina realmente no le importan: para su tipo de elemento de matriz específico, tienen exactamente el mismo efecto.

Los tipos de inicialización pueden ser un poco tediosos, pero en este caso es trivial. Para:

public:
    X()
    : m_array()
    {}

desde el lista de expresiones entre paréntesis están vacíos, se produce la inicialización del valor. Del mismo modo para:

public:
    X()
    : m_array{}
    {}

se produce la inicialización de la lista y, posteriormente, la inicialización del valor desde el brace-init-list esta vacio.


Para dar una respuesta más completa, veamos §8.5 de N4140.

  1. Si no se especifica ningún inicializador para un objeto, el objeto se inicializa de forma predeterminada. Cuando se obtiene almacenamiento para un objeto con duración de almacenamiento automático o dinámico, el objeto tiene una valor indeterminadoy si no se realiza ninguna inicialización para el objeto, ese objeto retiene un valor indeterminado hasta que se reemplaza ese valor (5.17).

Esto valor indeterminado es a lo que te refieres como valores basura.

  1. A cero inicializar un objeto o referencia de tipo T significa:

    — si T es un tipo de matriz, cada elemento se inicializa en cero

  2. A inicializar valor un objeto de tipo T significa:

    — si T es un tipo de clase (posiblemente cv-calificado) … entonces el objeto se inicializa por defecto; …

    — si T es un tipo de matriz, entonces cada elemento se inicializa con un valor;

    — de lo contrario, el objeto se inicializa a cero.

  3. La semántica de los inicializadores es la siguiente. … — Si el inicializador es un (sin paréntesis) braced-init-listel objeto o referencia se inicializa en lista (8.5.4).

    — Si el inicializador es (), el objeto se inicializa con valor.

Hasta ahora, está claro que la inicialización del valor hará que cada elemento de la matriz sea cero, ya que int no es un tipo de clase. Pero aún no hemos cubierto la inicialización de listas y la inicialización de agregados, ya que una matriz es un agregado.

§8.5.4:

  1. Lista de inicialización de un objeto o referencia de tipo T se define de la siguiente manera:

    — Si T es un agregado, se realiza la inicialización del agregado (8.5.1).

Y volviendo a §8.5.1:

  1. si hay menos cláusulas de inicialización en la lista que hay miembros en el agregado, entonces cada miembro no inicializado explícitamente se inicializará a partir de su inicializador de llave o igual
    o, si no hay inicializador de llave o igualde una lista de inicializadores vacía (8.5.4).

Y terminamos de nuevo con §8.5.4:

  1. Lista de inicialización de un objeto o referencia de tipo T se define de la siguiente manera:

    — De lo contrario, si la lista de inicializadores no tiene elementos, el objeto se inicializa con valor.

Dado que atravesar el estándar (borrador) puede dejarlo sin aliento, le recomiendo preferencia cp ya que lo descompone bastante bien.

Enlaces relevantes:

preferencia cp:

Proyecto de norma:

Avatar de usuario de JHumphrey
JHumphrey

Los paréntesis funcionan en C++ 98 y requieren una inicialización cero, que es lo que desea. Verifiqué en gcc 4.3. Editar: se eliminó la declaración incorrecta sobre C++ 11. También confirmé que las llaves vacías realizan la inicialización de lista vacía usando clang 3.4 con -std=c++11.

  • La parte sobre C++ 11 es incorrecta. Él {} en : m_array{} es un braced-init-list (No un std::initializer_list) y muy bien puede estar vacío. este vacio braced-init-list realiza la inicialización de valor de la matriz, lo que conduce a la inicialización cero de la int elementos.

    – mojar

    9 dic 2014 a las 20:05


¿Ha sido útil esta solución?