2010-11-04 10 views
7

Sé que generalmente inicializa una variable de miembro estática desde dentro de un archivo .cpp. Pero mi pregunta es: ¿por qué tiene?¿Por qué tienes que inicializar una variable de miembro estática de C++?

He aquí un ejemplo:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

main() { 
    int sz = A::x.size(); 
} 

Esto da un error del compilador: undefined reference to 'A::x'

Sin embargo, esto:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

// Initialize static member 
vector<int> A::x; 

main() { 
    int sz = A::x.size(); 
} 

compila y funciona muy bien.

Entiendo si estaba inicializando el vector usando algo que no sea el constructor predeterminado, pero no lo estoy. Solo quiero crear un vector de tamaño 0. Seguramente, a los miembros estáticos se les tendrá que asignar memoria en la inicialización del programa, entonces, ¿por qué el compilador simplemente no usa el constructor predeterminado?

Respuesta

14

Eso no es sobre la inicialización, se trata de definición. O más precisamente: se trata de saber qué unidad de compilación (.cpp) llevará a cabo el objeto (que se definirán de manera inequívoca en alguna parte)

Por lo tanto, lo que se necesita es simplemente puso la definición alguna parte, en un lugar único, que es un cpp, para que el compilador sepa que cuando se llama al objeto estático de la clase, se define allí y en ningún otro lugar. (Si intenta definir su estática en un encabezado, cada cpp que incluya este encabezado tendrá una definición, lo que imposibilitará saber dónde debe definirse, y se inicializará manualmente si es necesario) .

+2

+1 pero debe eliminar uno de los dups. Para los objetos, RAII hace que la inicialización (aunque solo sea por el constructor predeterminado) sea una consecuencia de la definición. ¿Esto funciona para punteros crudos, tipos integrados como 'int'? –

+0

Quería decir que puede agregar la inicialización allí si lo desea. Agregaré la precisión. – Klaim

+0

@Steve Los constructores de tipo POD son solo sintácticos, por lo que sí funciona, pero en realidad no hace nada (o para ser aún más preciso, no permite hacer nada, según el estándar de C++). –

2

Lo que usted llama inicialización es definición. Debe definir el miembro estático en alguna parte. La parte dentro de la clase es solo una declaración.

Esto se debe principalmente a que tener una definición dentro del encabezado causaría grandes problemas (ya que no podría incluir ese encabezado en más de una unidad de traducción sin causar múltiples definiciones).

8

Lo está viendo desde el punto de una sola unidad de compilación.

Pero el lenguaje tiene que suponer que potencialmente puede haber varias unidades de compilación. Entonces, ¿en qué unidad de compilación se creó el objeto estático? Básicamente, el compilador no puede tomar esa decisión y el ingeniero debe tomar la decisión.

3

undefined reference to 'A::x' no es un error de compilación; es un error del enlazador. Significa que no se puede encontrar una definición de A::x en ninguna de las unidades de traducción que se vinculan entre sí para formar su programa. Las variables de miembros estáticos tienen enlaces externos y deben definirse en exactamente una unidad de traducción. Cualquier cosa con enlaces externos no tendrá una definición generada por el compilador a menos que usted escriba uno.

Cuestiones relacionadas