new literal initialize initial cpp array c++ initialization initialization-list array-initialization

c++ - literal - initialize array cpp



Zero-Initialize miembro de la matriz en la lista de inicialización (3)

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

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

Para una variable local, hay una forma directa de inicializar en cero (ver here ):

int myArray[10] = {};

Además, el miembro de la clase m_array claramente necesita ser inicializado, ya que los m_array de inicialización por defecto solo dejarán basura aleatoria, como se explica here .

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

Con paréntesis:

public: X() : m_array() {}

Con tirantes:

public: X() : m_array{} {}

¿Son ambos correctos? ¿Hay alguna diferencia entre los dos en C ++ 11?


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

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

Inicializar cualquier otro tipo de agregado (incluidas las matrices) con {} inicializa la lista, y es equivalente a inicializar cada uno de los miembros del agregado con {} .

La inicialización de cualquier tipo de referencia con {} construye un objeto temporal, que se inicializa desde {} , y enlaza la referencia a ese temporal.

La inicialización de 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 de valor. No puede tener matrices de referencias, por lo que no pueden ser una excepción. Es posible que pueda construir matrices de tipos de clases agregadas 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 no son realmente importantes para usted: para su tipo de elemento de matriz específico, tienen exactamente el mismo efecto.


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


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

public: X() : m_array() {}

como la lista de expresiones entre los paréntesis está vacía, 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 ya que la lista de iniciación de brace está vacía.

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

  1. Si no se especifica un inicializador para un objeto, el objeto se inicializa por defecto. Cuando se obtiene el almacenamiento para un objeto con duración de almacenamiento automático o dinámico, el objeto tiene un valor indeterminado , y si no se realiza la inicialización del objeto, ese objeto retiene un valor indeterminado hasta que ese valor se reemplaza (5.17).

Este valor indeterminado es lo que usted denomina valores de basura.

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

    - Si T es un tipo de matriz, cada elemento está inicializado en cero

  2. Para inicializar con valor un objeto de tipo T significa:

    - si T es un tipo de clase (posiblemente cv calificado) ... entonces el objeto está inicializado por defecto; ...

    - si T es un tipo de matriz, entonces cada elemento está inicializado con valores;

    - De lo contrario, el objeto es cero inicializado.

  3. La semántica de los inicializadores es la siguiente. ... - Si el inicializador es una lista-iniciada con paréntesis (no entre paréntesis), el objeto o la referencia se inicializa en la lista (8.5.4).

    - Si el inicializador es (), el objeto está inicializado con valores.

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. La inicialización de lista de un objeto o referencia de tipo T se define de la siguiente manera:

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

Y volviendo a §8.5.1:

  1. Si hay menos cláusulas de inicialización en la lista de las que hay miembros en el agregado, entonces cada miembro que no se inicialice explícitamente se inicializará desde su inicializador de corsé o igual o, si no hay un inicializador de corsé o igual , de una lista de inicialización vacía (8.5.4).

Y terminamos con §8.5.4 de nuevo:

  1. La inicialización de lista 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 valores.

Ya que atravesar el estándar (draft) puede quitarte el aliento, recomiendo cppreference ya que lo desglosa bastante bien.

Enlaces relevantes:

cppreference:

Proyecto de norma: