La lista de inicializadores se utiliza para inicializar los miembros de datos de una clase. La lista de miembros que se inicializarán se indica con constructor como una lista separada por comas seguida de dos puntos. El siguiente es un ejemplo que usa la lista de inicializadores para inicializar x e y de la clase Point.
C++
#include<iostream> using namespace std; class Point { private: int x; int y; public: Point(int i = 0, int j = 0):x(i), y(j) {} /* The above use of Initializer list is optional as the constructor can also be written as: Point(int i = 0, int j = 0) { x = i; y = j; } */ int getX() const {return x;} int getY() const {return y;} }; int main() { Point t1(10, 15); cout<<"x = "<<t1.getX()<<", "; cout<<"y = "<<t1.getY(); return 0; } /* OUTPUT: x = 10, y = 15 */
El código anterior es solo un ejemplo de la sintaxis de la lista de inicializadores. En el código anterior, x e y también se pueden inicializar fácilmente dentro del constructor. Pero hay situaciones en las que la inicialización de los miembros de datos dentro del constructor no funciona y se debe usar la lista de inicializadores. Los siguientes son tales casos:
1) Para la inicialización de miembros de datos const no estáticos:
los miembros de datos const deben inicializarse utilizando la lista de inicializadores. En el siguiente ejemplo, «t» es un miembro de datos constantes de la clase Prueba y se inicializa mediante la Lista de inicializadores. La razón para inicializar el miembro de datos const en la lista de inicializadores es que no se asigna memoria por separado para el miembro de datos const, está doblada en la tabla de símbolos por lo que necesitamos inicializarla en la lista de inicializadores.
Además, es un constructor parametrizado y no necesitamos llamar al operador de asignación, lo que significa que estamos evitando una operación adicional.
C++
#include<iostream> using namespace std; class Test { const int t; public: Test(int t):t(t) {} //Initializer list must be used int getT() { return t; } }; int main() { Test t1(10); cout<<t1.getT(); return 0; } /* OUTPUT: 10 */
2) Para la inicialización de miembros de referencia: los miembros de
referencia deben inicializarse utilizando la lista de inicializadores. En el siguiente ejemplo, «t» es un miembro de referencia de la clase Prueba y se inicializa mediante la Lista de inicializadores.
C++
// Initialization of reference data members #include<iostream> using namespace std; class Test { int &t; public: Test(int &t):t(t) {} //Initializer list must be used int getT() { return t; } }; int main() { int x = 20; Test t1(x); cout<<t1.getT()<<endl; x = 30; cout<<t1.getT()<<endl; return 0; } /* OUTPUT: 20 30 */
3) Para la inicialización de objetos miembro que no tienen un constructor predeterminado:
en el siguiente ejemplo, un objeto «a» de la clase «A» es un miembro de datos de la clase «B» y «A» no tiene un constructor predeterminado. La lista de inicializadores debe usarse para inicializar «a».
C++
#include <iostream> using namespace std; class A { int i; public: A(int ); }; A::A(int arg) { i = arg; cout << "A's Constructor called: Value of i: " << i << endl; } // Class B contains object of A class B { A a; public: B(int ); }; B::B(int x):a(x) { //Initializer list must be used cout << "B's Constructor called"; } int main() { B obj(10); return 0; } /* OUTPUT: A's Constructor called: Value of i: 10 B's Constructor called */
Si la clase A tenía constructores predeterminados y parametrizados, entonces la lista de inicializadores no es obligatoria si queremos inicializar «a» usando el constructor predeterminado, pero sí lo es para inicializar «a» usando el constructor parametrizado.
4) Para la inicialización de los miembros de la clase base: como en el punto 3, el constructor parametrizado de la clase base solo se puede llamar usando la Lista de inicializadores.
C++
#include <iostream> using namespace std; class A { int i; public: A(int ); }; A::A(int arg) { i = arg; cout << "A's Constructor called: Value of i: " << i << endl; } // Class B is derived from A class B: A { public: B(int ); }; B::B(int x):A(x) { //Initializer list must be used cout << "B's Constructor called"; } int main() { B obj(10); return 0; }
5) Cuando el nombre del parámetro del constructor es el mismo que el miembro de datos
Si el nombre del parámetro del constructor es el mismo que el nombre del miembro de datos, entonces el miembro de datos debe inicializarse usando este puntero o la Lista de inicializadores. En el siguiente ejemplo, tanto el nombre del miembro como el nombre del parámetro para A() es “i”.
C++
#include <iostream> using namespace std; class A { int i; public: A(int ); int getI() const { return i; } }; A::A(int i):i(i) { } // Either Initializer list or this pointer must be used /* The above constructor can also be written as A::A(int i) { this->i = i; } */ int main() { A a(10); cout<<a.getI(); return 0; } /* OUTPUT: 10 */
6) Por motivos de rendimiento:
es mejor inicializar todas las variables de clase en la lista de inicializadores en lugar de asignar valores dentro del cuerpo. Considere el siguiente ejemplo:
C++
// Without Initializer List class MyClass { Type variable; public: MyClass(Type a) { // Assume that Type is an already // declared class and it has appropriate // constructors and operators variable = a; } };
Aquí el compilador sigue los siguientes pasos para crear un objeto de tipo MyClass
1. El constructor de tipo se llama primero para «a».
2. Construcción predeterminada «variable»
3. El operador de asignación de «Tipo» se llama dentro del cuerpo del constructor MyClass() para asignar
variable = a;
4. Y luego, finalmente, el destructor de «Tipo» se llama «a» ya que queda fuera del alcance.
Ahora considere el mismo código con el constructor MyClass() con la lista de inicializadores
C++
// With Initializer List class MyClass { Type variable; public: MyClass(Type a):variable(a) { // Assume that Type is an already // declared class and it has appropriate // constructors and operators } };
Con la lista de inicializadores, el compilador sigue los siguientes pasos:
1. 1. Primero se llama al constructor de tipo para «a».
2. Se llama al constructor parametrizado de la clase «Tipo» para inicializar: variable (a). Los argumentos en la lista de inicializadores se usan para copiar la construcción «variable» directamente.
3. El destructor de “Tipo” se llama “a” ya que sale fuera de alcance.
Como podemos ver en este ejemplo, si usamos la asignación dentro del cuerpo del constructor, hay tres llamadas de función: constructor + destructor + una llamada de operador de asignación adicional. Y si usamos la lista de inicializadores, solo hay dos llamadas de función: copiar constructor + llamada al destructor. Vea esta publicación para ver un ejemplo de ejecución sobre este punto.
Esta penalización de asignación será mucho mayor en aplicaciones “reales” donde habrá muchas de estas variables. Gracias a ptr por agregar este punto.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA