Test Foro de elhacker.net SMF 2.1

Programación => Programación C/C++ => Mensaje iniciado por: class_OpenGL en 14 Octubre 2017, 21:06 PM

Título: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: class_OpenGL en 14 Octubre 2017, 21:06 PM
Hola, muy buenas.

Mi duda es la siguiente: imaginemos que tenemos una clase con un solo constructor, que necesita parámetros. ¿Podríamos crear e instanciar un arreglo de objetos tipo <esa clase> con algo parecido a la siguiente sintaxis?

Código (cpp) [Seleccionar]
Objeto objetos[NUM_OBJETOS] = {0};

En este caso, el constructor del objeto recibiría como parámetro un entero, por lo que se haría 'conversión' implícita.

Muchas gracias
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: ivancea96 en 14 Octubre 2017, 22:38 PM
En el array, pones los parámetros para construir los objetos entre llaves:
Código (cpp) [Seleccionar]
string strs[] = {{"a", 1}, {"b", 1}, {"c", 1}};
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: class_OpenGL en 14 Octubre 2017, 22:47 PM
No era eso lo que quería decir. A veces me explico muy mal xD. Siguiendo con el ejemplo de string que has propuesto, mi intención es crear un vector de string de la siguiente forma:

Código (cpp) [Seleccionar]
std::string cadenas[100] = {"Cadena"};

El resultado esperado por mi sería que cada cadena sea inicializada con "Cadena". Poniendo esa línea, el compilador me tira error.
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: ivancea96 en 14 Octubre 2017, 23:49 PM
Lo que comentas no es posible.
De todos modos, en C++11 es preferible utilizar clases como vector en vez de arrays de C.
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: class_OpenGL en 14 Octubre 2017, 23:51 PM
De acuerdo, usaré los vectores de la STL. Gracias! (una pena que no se pueda)
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: srWhiteSkull en 14 Octubre 2017, 23:57 PM
Claro que puedes crear un array de punteros. Y la linea que muestras esta bien, deberia compilar sin problema. Muestra el error que te da el compilador.
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: ivancea96 en 15 Octubre 2017, 00:02 AM
Cita de: srWhiteSkull en 14 Octubre 2017, 23:57 PM
Claro que puedes crear un array de punteros. Y la linea que muestras esta bien, deberia compilar sin problema. Muestra el error que te da el compilador.

Habla de inicializar todos los elementos de un array con un mismo conjunto de parámetros.
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: class_OpenGL en 15 Octubre 2017, 00:07 AM
Esto es raro. Si intento compilar el ejemplo del string:

Código (c++) [Seleccionar]
std::string cadenas[100] = {"Cadena"};

si que funciona, pero si lo hago para un tipo de dato definido por mi:

Código (c++) [Seleccionar]
#include <iostream>

class Objeto {
public:
    Objeto(int n);
};

int main() {
    Objeto cadenas[100] = {1};
   
    return 0;
}


si que me da error:

Citarprueba.cpp:9:29: error: no se puede convertir '<lista inicializador dentro de llaves>()' de '<lista inicializador dentro de llaves>' a 'Objeto'
     Objeto cadenas[100] = {1};
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: srWhiteSkull en 15 Octubre 2017, 00:36 AM
Para tu objeto definido no funcionaria asi, tendrias que currartelo, por ejemplo, sobrecargando operadores, y claro esta, dentro de la clase tendrias que gestionar los punteros, reservar memoria, etc... pero podrias conseguir algo asi :

Código (cpp) [Seleccionar]
//Definir un array o arreglo de 4 elementos
Objeto *varios=new Objeto(1,32,55,6); // con argumentos indefinidos (...)

// luego
std:cout << *varios[0].id; // mostraria 1, por ejemplo (sobrecarga los corchetes para acceder al resto de elementos)


o sino quieres complicarte usar un vector como bien dice ivancea96.
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: class_OpenGL en 15 Octubre 2017, 00:46 AM
Bueno, tras realizar algunas comprobaciones tecleando código, he llegado a las siguientes conclusiones:

Lo que hace C++11 es decir: vale, te permito crear un arreglo e inicializarlo con una initializer_list con un número de elementos menor o igual al tamaño del arreglo, pero bajo las siguientes condiciones:



Ejemplo de la segunda condición:

Código (c++) [Seleccionar]
#include <iostream>
#include <initializer_list>

class Objeto {
private:
   int u;
   
public:
   Objeto(int n);
   Objeto(const std::initializer_list<char> &n);
   
   void Imprimir();
};

int main() {
   Objeto cadenas[3] = {1, 1};
   
   std::cout << std::endl;
   
   for(int i = 0; i < 3; i++)
       cadenas[i].Imprimir();
   
   return 0;
}

Objeto::Objeto(int n) {
   std::cout << n << std::endl;
   
   u = 1;
}
   
Objeto::Objeto(const std::initializer_list<char> &n) {
   std::initializer_list<char>::iterator it;
   
   std::cout << "Initializer (size = " << n.size() << "): ";
   for(it = n.begin(); it != n.end(); it++)
       std::cout << *it << ' ';
   std::cout << std::endl;
   
   u = 2;
}

void Objeto::Imprimir() {
   std::cout << u << std::endl;
}


La salida del siguiente código:

Citar1
1
Initializer (size = 0):

1
1
2

Como podéis ver, para los primeros elementos, se llama al constructor de parámetro tipo 'int' (aquí pongo un poco de conversión implícita), y cuando se queda sin elementos, se llama al constructor con el initializer_list con cero valores. Si hubieramos definido otro constructor con initializer_list con tipo, por ejemplo, std::string, hubiera dado error de ambigüedad.

Espero haberme explicado bien. Esta es una particularidad de C++ que desconocía por completo
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: srWhiteSkull en 15 Octubre 2017, 02:29 AM
A ver, ahi eso del initializer_list no lo estas usando, ya que todo lo que esta dentro de las llaves pasa por el primer constructor, y para que pasara al otro constructor el valor en vez de un entero tendria que ser algo contenido entre llaves... pero olvidate de esto. Tu codigo tal como lo tienes funciona bien, instancias el Objeto pero no correctamente, ya que de esa forma estas alojando los objetos en la pila de cabecera, un pequeño espacio reservado definido en el compilador para guardar variables estaticas. Lo recomendable es usar el new en un vector o hacerlo como te conté.

Te muestro un codigo para que lo comprendas, mira hacia donde apunta cada elemento:

Código (cpp) [Seleccionar]
#include <iostream>
//#include <initializer_list>

class Objeto {
private:
   int u;

public:
   Objeto(int n);
   //Objeto(const std::initializer_list<char> &n);
   void Imprimir();
};

int main() {
   Objeto cadenas[2] = {5, 9}; // estatico, en la pila
   Objeto *instanciao = new Objeto(666); // dinamico
   int y=8; // estatico, en la pila

   std::cout << &cadenas[0] << " " << &cadenas[1] << " " << &y << " " << instanciao << std::endl;

   for(int i = 0; i < 2; i++)
       cadenas[i].Imprimir();

   return 0;
}

Objeto::Objeto(int n) {
   std::cout << n << std::endl;

   u = n;
}

/*Objeto::Objeto(const std::initializer_list<char> &n) {
   std::initializer_list<char>::iterator it;

   std::cout << "Initializer (size = " << n.size() << "): ";
   for(it = n.begin(); it != n.end(); it++)
       std::cout << *it << ' ';
   std::cout << std::endl;


   u = 2;
}*/

void Objeto::Imprimir() {
   std::cout << u << std::endl;
}


Como habras observado el puntero instanciao apunta a un segmento diferente del resto  ;)
Título: Re: (Consulta/C++11) Es posible inicializar un arreglo de objetos en la misma línea?
Publicado por: class_OpenGL en 15 Octubre 2017, 09:24 AM
Si que se te está usando. Se usa cuando el número de elementos del vector es mayor que el número de elementos del initializer_list (aclarado con ejemplos y demostrado para mi compilador).