2009-07-17 26 views
8

Código debe explicar cosas:C++: puntero de miembro inicializado? muestra

class A 
{ 
    B* pB; 
    C* pC; 
    D d; 

    public : 
    A(int i, int j) : d(j) 
    { 
     pC = new C(i, "abc"); 
    } // note pB is not initialised, e.g. pB(NULL) 

    ... 
}; 

Obviamente pB debe ser inicializado a NULL explícita para ser seguro (y claro), pero, tal y como está, cuál es el valor de Pb después de la construcción de A? ¿Está inicializado por defecto (que es cero?) O no (es decir, indeterminado y lo que haya en la memoria). Me doy cuenta de que la inicialización en C++ tiene unas pocas reglas justas.

Creo que no se ha inicializado por defecto; como se ejecuta en modo de depuración en Visual Studio, ha establecido pB apuntando a 0xcdcdcdcd, lo que significa que la memoria ha sido new'd (en el montón) pero no se ha inicializado. Sin embargo, en el modo de lanzamiento, pB siempre apunta a NULL. ¿Es esto solo por casualidad y, por lo tanto, no se puede confiar en él? o estos compiladores lo inicializan para mí (incluso si no está en el estándar)? También parece ser NULL cuando se compila con el compilador de Sun en Solaris.

Realmente estoy buscando una referencia específica a la norma para decir de una forma u otra.

Gracias.

+4

Indeterminado (y algunos compiladores advertirán), pero no tengo el C++ estándar a mano ... – ephemient

+4

B es un puntero al azar en la naturaleza. Nota. En el modo de depuración, la mayoría del compilador lo inicializará en NULL (supuestamente para ayudar en la depuración). Pero en el modo de lanzamiento tendrá el valor que estaba previamente en la memoria. –

Respuesta

11

Aquí está el pasaje pertinente enfrente él estándar:

12.6.2 Inicialización de bases y miembros [class.base.init]

4 Si un miembro de datos no estático dado o clase base no es nombrados por un miem-
inicializador-id en la mem-inicializador lista , entonces

--Si la entidad es un conjunto de datos no estáticos miembro de (posiblemente cv-cualificado) tipo de clase (o conjunto de ellos) o una clase base, y la clase de entidad es una clase no POD, la entidad se inicializa por defecto (dcl.init). Si la entidad es un miembro de datos no estático de un tipo const-calificado, , la clase de entidad tendrá un constructor predeterminado declarado por el usuario.

- De lo contrario, la entidad no es inicializada. Si la entidad es tipo const calificada o tipo de referencia, o de un (posiblemente cv-quali- fied) tipo de clase POD (o una matriz de la misma) que contiene (directamente o indirectamente) un miembro de un tipo const-calificado, el programa es ill- formado.

Después de la llamada a un constructor para clase X ha completado, si un miembro

de X no es ni especifica en MEM-inicializadores la del constructor, ni
inicializado-default , ni inicializado durante la ejecución de el cuerpo de
el constructor, el miembro tiene valor indeterminado.

+2

por lo que no está inicializado, y puede señalar cualquier cosa. El contenido puede ser completado por la implementación, es decir, fdfdfdfd para la biblioteca debugheap. – xtofl

1

Creo que esto es un artefacto de los buenos viejos tiempos C cuando no se podían tener expectativas sobre qué contiene la memoria asignada. A medida que los estándares progresaron a C++, se mantuvo esta "convención". A medida que los compiladores de C++ se desarrollaron, los autores individuales se encargaron de "arreglar" este problema. Por lo tanto, su millaje puede variar dependiendo de su compilador de su elección.

El "0xcdcdcdcd" parece ser un patrón fácilmente identificable que "ayuda" a depurar el código. Es por eso que no se muestra en el modo de lanzamiento.

Espero que esto haya ayudado de alguna manera y buena suerte.

0

Los punteros no inicializados pueden señalar cualquier cosa. Algunos proveedores de compiladores te ayudarán y harán que apunten a 0 o 0xcdcdcdcd o lo que sea.

Para asegurarse de que su código sea seguro y portátil, siempre debe inicializar sus punteros. ya sea a 0 o a un valor válido.

p. Ej.

C* pc = 0; 

o

C* pc = new C(...); 

Si siempre inicializar punteros a 0, entonces esto es seguro:

if (!pc) 
    pc = new C(...); 

Si no inicializar entonces tienes forma de saber inicializado y punteros sin inicializar aparte.

Como un lado, no existe tal palabra clave en C++ como NULL. La mayoría de los compiladores definen NULL como 0, pero no se considera portátil para usarlo. El nuevo estándar C++ 0x introducirá una nueva palabra clave, nullptr, de modo que cuando eso salga finalmente tendremos una constante de puntero nulo portátil.

0

El valor de pB no está definido. Puede o no ser consistentemente el mismo valor, generalmente depende de lo que estaba previamente en el mismo lugar en la memoria antes de la asignación de una instancia particular de A.

0

Los punteros no inicializados se permiten básicamente contener un valor aleatorio, aunque algunos compiladores tienden a llenarlos con 0 o algún otro valor reconocible, especialmente en modo de depuración.

En mi humilde opinión esto se debe al diseño de C++ "no pagues por lo que no usas". Si no lo considera importante, el compilador no necesita pagar el gasto de inicializar la variable por usted. Por supuesto, una vez que haya perseguido un puntero al azar, puede ser prudente inicializarlo la próxima vez ...

+0

¿No te refieres a "* No * pagar por lo que no usas"? – Imagist

+0

Errr .... Sí. Gracias por señalar eso. –

4

De acuerdo con C++0x standard sección 12.6.2.4, en el caso de su variable de puntero, si se pone 't incluirlo en la lista de inicialización y no lo establece en el cuerpo del constructor, entonces tiene un valor indeterminado. 0xCDCDCDCD y 0 son dos valores posibles, como cualquier otra cosa. :-)

0

Es raro que recomiende no aprender algo sobre el idioma que está utilizando, pero en este caso, si se inicializa o no pB no es información útil. Solo inicialízalo. Si se inicializa automáticamente, el compilador optimizará la inicialización adicional. Si no es así, ha agregado una instrucción de procesador adicional y ha evitado una gran cantidad de posibles errores.

Cuestiones relacionadas