2010-05-12 12 views
20

Digamos que tengo la siguiente declaración de estructura (estructura simple sin constructor).¿Puede un miembro struct ser zero-init desde la lista de inicializadores del constructor sin llamar a memset?

struct Foo 
{ 
    int x; 
    int y; 
    int z; 
    char szData[DATA_SIZE]; 
}; 

Ahora digamos que esta estructura es un miembro de una clase de C++ de la siguiente manera:

class CFoobar 
{ 
    Foo _foo; 
public: 
    CFoobar(); 
}; 

Si declaro el constructor de CFoobar de la siguiente manera:

CFoobar::CFoobar() 
{ 
    printf("_foo = {%d, %d, %d}\n", _foo.x, _foo.y,_foo.z); 
    for (int x = 0; x < 100; x++) 
     printf("%d\n", _foo.szData[x]); 
} 

Como era de esperar, cuando El constructor de CFoobar se ejecuta, los datos basura se imprimen Obviamente, la solución más fácil es memset o ZeroMemory & _foo. Es lo que siempre he hecho ...

Sin embargo, me di cuenta de que si se añade a la lista de _foo inicialización del constructor sin parámetros de la siguiente manera:

CFoobar::CFoobar() 
: _foo() 
{ 

Que esto parece de finalización y el miembro variables de _foo. Al menos ese fue el caso con g ++ en Linux.

Ahora aquí está mi pregunta: ¿Es este C++ estándar, o es este comportamiento específico del compilador?

Si es un comportamiento estándar, ¿alguien puede citarme una referencia de una fuente oficial? ¿Algún "truco" con respecto al comportamiento implícito de inicio cero con estructuras y clases más complicadas?

Respuesta

11

Sí, este comportamiento se define de acuerdo con la norma. 12.6.2 [class.base.init]/3: "si se omite la lista de expresiones del mem-initializer, la clase base o el subobjeto miembro es value-initialized."

Se advirtió, sin embargo, si Foo no era un tipo POD, pero todavía tenía ningún constructor-declarada de usuario (por ejemplo, tenía un tipo std::string) a continuación algunos compiladores muy populares serían no correctamente valor inicializar ella.

Todos los compiladores, que yo sepa no realizan correctamente valor de inicialización de miembros de la cápsula cuando se utiliza () como el inicializador en un inicializador lista constructor.

+0

"algunos compiladores populares" = VC6 Supongo? Porque no he visto el comportamiento incorrecto en ningún compilador de los últimos 10 años. – MSalters

+0

@MSalters: Y los compiladores VS2005 y VS2008, desafortunadamente. No he probado esto en VS2010. –

+0

@MSalters: no solo se aplica a miembros de estructura que no sean POD sin un constructor declarado por el usuario; otros tipos funcionan correctamente Hay varios informes sobre esto en Connect. Este es uno que encontré: https://connect.microsoft.com/VisualStudio/feedback/details/484295/vc-does-not-value-initialize-members-of-derived-classes-without-user-declared-constructor –

2

Me resulta difícil de leer la norma, pero me pareció que pienso:

Para valor inicializar un objeto de tipo T significa:
si T es un tipo de clase no unión sin constructor declarado por el usuario, entonces cada miembro de datos no estáticos y base- componente de clase de T tiene un valor inicializado La inicialización del valor para dicho objeto de clase puede implementarse inicializando en cero el objeto y luego llamando al constructor predeterminado.

Sección 8.5

+0

8.5 debe leerse junto con 12.6.2 para saber que este inicializador de miembros realmente requiere _value-initialization_. –

1

Es el equivalente de float foo = float();

Será cero el objeto, incluso si la representación de valor es no todos los bits de cero. Es decir. es incluso mejor que memset().

Cuestiones relacionadas