2010-03-10 25 views
135

¿El constructor predeterminado (creado por el compilador) inicializa los tipos incorporados?¿El constructor predeterminado inicializa los tipos incorporados?

+14

Me sorprendió este es un CW - esto tiene realmente una respuesta correcta, no es subjetiva, no es un tema de discusión . –

+0

Sí, es una decisión extraña. ¿Por qué se movió esto a CW? –

+1

Como OP es un nuevo usuario, creo que acaba de cometer un error. – Gorpik

Respuesta

1

De acuerdo con la norma, no menos que inicializar explícitamente en lista de inicialización

+2

Bueno, no se puede especificar nada en el constructor predeterminado * creado por el compilador * – Gorpik

+2

@Gorpik - Punto tomado ... pero si digo explícitamente inicializar, quiero decir que uno tiene que proporcionar explícitamente el constructor predeterminado – mukeshkumar

+0

@hype: I lo sé, pero OP especificó que estaba hablando sobre el constructor predeterminado creado por la computadora, no uno que usted mismo proporciona. – Gorpik

-6

No. El constructor por defecto asigna memoria y llama al constructor sin argumentos de los padres.

+5

Y el constructor no-arg de cualquier miembro que no sea POD. –

+0

¿El constructor asigna memoria, o el compilador "asigna" memoria para la instancia y luego invoca al constructor? – visitor

+4

Esta respuesta es bastante errónea ... 1/El Constructor no asigna memoria, la inicializa. 2/La pregunta era acerca de una función incorporada y esta respuesta es acerca de las clases para padres ... ¿cómo es que esta respuesta errónea fuera del tema obtuvo 8 votos? –

-3

Técnicamente, los inicializa, utilizando su constructor predeterminado, que por cierto no hace más que asignarles la memoria.

Si lo que quería saber es si están configurados para algo sensato como 0 para int s, entonces la respuesta es "no".

+3

constrctor no asigna memoria.Constructor se ejecuta después de la asignación de memoria.Por favor corrígeme si estoy equivocado. – ZoomIn

1

Como han indicado los altavoces anteriores, no, no están inicializados.

Esto es realmente una fuente de errores realmente extraños, ya que los sistemas operativos modernos tienden a llenar regiones de memoria recién asignadas con ceros. Si espera eso, podría funcionar la primera vez. Sin embargo, a medida que su aplicación sigue ejecutándose, delete -ing y new -ing objetos, tarde o temprano terminará en una situación en la que espera ceros pero se encuentra un residuo distinto de cero de un objeto anterior.

Entonces, ¿por qué es esto, entonces, no todos los datos new -ed recién asignados? Sí, pero no siempre del sistema operativo. El sistema operativo tiende a trabajar con fragmentos de memoria más grandes (por ejemplo, 4 MB a la vez), por lo que todas las pequeñas asignaciones y desasignaciones de una sola palabra-aquí-tres-bytes-allí se manejan en uyserpace, y por lo tanto no se ponen a cero.

PS. Escribí "tender", es decir, ni siquiera puede confiar en el éxito la primera vez ...

16

Para todos los fines prácticos - no.


Sin embargo, para las implementaciones que son técnicamente compatible con el estándar C++, la respuesta es que depende de si el objeto es POD o no y de cómo se inicialice. Según el estándar de C++:

MyNonPodClass instance1;//built in members will not be initialized 
MyPodClass instance2;//built in members will be not be initialized 
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized 
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized 

Sin embargo, en el mundo real, esto no es bien soportado de manera no lo use.


Las partes pertinentes de la norma son la sección 8.5.5 y 8.5.7

+0

¿Qué pasa con los globales, no siempre se inicializan en cero? – fredoverflow

+1

Para todos menos el primero, no se llama al constructor predeterminado. De hecho, sus ctors predeterminados hacen lo mismo (no inicializan nada); después de todo, todos son de la misma clase. En el cuarto, el valor del compilador solo inicializa el POD y no llama al constructor predeterminado. –

+0

@FredOverflow, todo el ámbito del espacio de nombres y los objetos estáticos locales o de clase se inicializan en cero, independientemente de su tipo (podrían ser las clases más complejas que existen, aún así se inicializarán en cero). –

10

No estoy muy seguro de lo que quieres decir, pero:

struct A { int x; }; 

int a; // a is initialized to 0 
A b; // b.x is initialized to 0 

int main() { 
    int c;   // c is not initialized 
    int d = int(); // d is initialized to 0 

    A e;   // e.x is not initialized 
    A f = A();  // f.x is initialized to 0 
} 

En cada caso donde diga "no inicializado": es posible que su compilador le proporcione un valor constante, pero el estándar no lo requiere.

Se emite una gran cantidad de movimientos manuales, incluso por mí, sobre cómo los tipos incorporados "en efecto" tienen un constructor predeterminado. En realidad, la inicialización predeterminada y la inicialización de valores son términos definidos en el estándar, que personalmente debo buscar cada vez. Solo las clases se definen en el estándar para tener un constructor predeterminado implícito.

135

El constructor predeterminado de una clase definido implícitamente (por el compilador) no inicializa los miembros de los tipos incorporados.

Sin embargo, debe tener en cuenta que, en algunos casos, la inicialización de una instancia de la clase puede realizarse por otros medios. No por constructor predeterminado, ni por constructor en absoluto.

Por ejemplo, existe una creencia generalizada incorrecta de que para la clase C la sintaxis C() siempre invoca el constructor predeterminado. En realidad, sin embargo, la sintaxis C() realiza lo que se llama value-initialization de la instancia de clase. Solo invocará el constructor predeterminado si es declarado por el usuario. (Eso está en C++ 03. En C++ 98, solo si la clase no es POD). Si la clase no tiene un constructor declarado por el usuario, entonces el C() no llamará al constructor predeterminado provisto por el compilador, sino que realizará un tipo especial de inicialización que no involucra al constructor de C en absoluto. En cambio, va a inicializar el valor directamente a cada miembro de la clase. Para los tipos incorporados, da como resultado una inicialización cero.

Por ejemplo, si la clase no tiene constructor

class C { 
    int x; 
}; 

-declarada usuario entonces el compilador implícitamente proporcionar una. El constructor compilador proporcionado no hará nada, lo que significa que no se inicializará C::x

C c; // Compiler-provided default constructor is used 
// Here `c.x` contains garbage 

Sin embargo, los siguientes inicializaciones se cero inicializar x porque utilizan la explícita () inicializador

C c = C(); // Does not use default constructor for `C()` part 
      // Uses value-initialization feature instead 
assert(c.x == 0); 

C *pc = new C(); // Does not use default constructor for `C()` part 
       // Uses value-initialization feature instead 
assert(pc->x == 0); 

la el comportamiento del inicializador () es diferente en algunos aspectos entre C++ 98 y C++ 03, pero no en este caso. Para la clase anterior C, será el mismo: el inicializador () realiza la inicialización cero de C::x.

Otro ejemplo de inicialización que se lleva a cabo sin la participación de constructor es, por supuesto, inicialización de agregados

C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. 
assert(c.x == 0); 

C d{}; // C++11 style aggregate initialization. 
assert(d.x == 0); 
+4

¡NOTA! Según http://stackoverflow.com/a/3931589/18775 hay un error en el compilador de Visual Studio C++ y el C c = C(); no siempre funciona –

+13

En C++ 11: ¿'C c {}' inicializará 'x' con' 0'? – towi

+0

¿Por qué el compilador me advierte entonces que 'tm birthday {0,0,0, t, m-1, j-1900};' sobre las inicializaciones perdidas. Reúno g ++ - 4.8 con * "inicializador faltante para el miembro 'tm :: tm_yday'" que el valor se deja unificado - y no el valor de valor inicializado con 0. ¿Será a '=' antes de que '{' sea un remedio? – towi

Cuestiones relacionadas