Inicializar una matriz miembro en el inicializador del constructor


class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

Creo que la razón es que los arrays solo se pueden inicializar con la sintaxis =, es decir:

int arr[3] = {1,3,4};

Preguntas

  1. ¿Cómo puedo hacer lo que quiero hacer (que es, inicializar una matriz constructor (no asignando elementos en el cuerpo)). ¿Es posible?
  2. ¿El estándar C++03 dice algo especial sobre la inicialización de agregados (incluyendo arrays) en inicializadores ctor? O la invalidez del código anterior es un corolario de algún otro reglas?
  3. ¿Las listas inicializadoras C++0x resuelven el problema?

P.d. Por favor, no mencione vectores, boost::arrays, y su superioridad a los arrays, que soy muy consciente de.

Author: Armen Tsirunyan, 2010-10-30

6 answers

  1. ¿Cómo puedo hacer lo que quiero hacer (es decir, inicializar una matriz en un constructor (no asignar elementos en el cuerpo)). ¿Es posible?

Sí. Está usando una estructura que contiene una matriz. Dices que ya lo sabes, pero entonces no entiendo la pregunta. De esta manera, hace inicializar un array en el constructor, sin asignaciones en el cuerpo. Esto es lo que hace boost::array.

¿Dice algo el estándar C++03 especial acerca de la inicialización de agregados (incluyendo arrays) en inicializadores ctor? ¿O la invalidez del código anterior es un corolario de algunas otras reglas?

Un inicializador mem utiliza la inicialización directa. Y las reglas de la cláusula 8 prohíben este tipo de cosas. No estoy exactamente seguro sobre el siguiente caso, pero algunos compiladores lo permiten.

struct A {
  char foo[6];
  A():foo("hello") { } /* valid? */
};

Ver este GCC PR para más detalles.

Do C++0x initializer lists solve the problema?

Sí, lo hacen. Sin embargo, su sintaxis no es válida, creo. Tienes que usar llaves directamente para disparar la inicialización de la lista

struct A {
  int foo[3];
  A():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};
 48
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-30 09:44:38

C++98 no proporciona una sintaxis directa para nada más que poner a cero (o para elementos que no sean POD, inicializar valores) el array. Para eso solo escribes C(): arr() {}.

Lo que Roger Pate está mal sobre las supuestas limitaciones de la inicialización agregada de C++0x, pero soy demasiado perezoso para buscarlo o comprobarlo, y no importa, ¿verdad? EDITAR: Roger estaba hablando de "C++03", lo malinterpreté como "C++0x". Lo siento, Roger. ☺

Una solución alternativa de C++98 para su código actual es envolver el array en un struct e inicializarlo desde una constante estática de ese tipo. Los datos tienen que residir en algún lugar de todos modos. De repente puede verse así:

class C 
{
public:
    C() : arr( arrData ) {}

private:
     struct Arr{ int elem[3]; };
     Arr arr;
     static Arr const arrData;
};

C::Arr const C::arrData = {{1, 2, 3}};
 25
Author: Cheers and hth. - Alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-19 09:02:24

Solución:

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};
 6
Author: Alexey Malistov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-30 09:25:38
  1. No, desafortunadamente.
  2. Simplemente no se puede en la forma que desee, ya que no está permitido por la gramática (más abajo). Solo puede usar inicialización similar a ctor y, como sabe, no está disponible para inicializar cada elemento en matrices.
  3. Creo que sí, ya que generalizan la inicialización en todos los ámbitos de muchas maneras útiles. Pero no estoy seguro de los detalles.

En C++03, la inicialización agregada solo se aplica con una sintaxis similar a la siguiente, que debe ser una sintaxis separada sentencia y no cabe en un inicializador ctor.

T var = {...};
 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-30 09:01:13

¿Qué tal

...
  C() : arr{ {1,2,3} }
{}
...

?

Compila bien en g++ 4.8

 1
Author: eold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-12 18:34:06

¿Desea iniciar una matriz de ints en su constructor? Apunte a una matriz estática.

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}
 -1
Author: DaveEff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-29 09:37:38