2010-03-20 31 views
14

memset se usa a veces para inicializar datos en un constructor como el ejemplo a continuación. ¿Funciona en general? ¿Es una buena idea en general?memset para la inicialización en C++

class A { 
public: 
    A(); 
private: 
    int a; 
    float f; 
    char str[35]; 
    long *lp; 
}; 

A::A() 
{ 
    memset(this, 0, sizeof(*this)); 
} 
+0

Puede usar el siguiente enfoque: http://stackoverflow.com/a/38103250/3223828 –

Respuesta

21

No utilizar memset. Es un holdover de C y no funcionará en los no POD. Específicamente, usarlo en una clase derivada que contenga funciones virtuales, o cualquier clase que contenga un componente no incorporado, provocará un desastre.

C++ proporciona una sintaxis específica para la inicialización:

class A { 
public: 
    A(); 
private: 
    int a; 
    float f; 
    char str[35]; 
    long *lp; 
}; 

A::A() 
    : a(0), f(0), str(), lp(NULL) 
{ 
} 

Para ser honesto, no estoy seguro, pero memset también podría ser una mala idea de puntos flotantes, ya que su formato no está especificado.

+1

También hay 'std :: fill' o' std :: fill_n' si necesita "memset" una matriz (o cualquier otra secuencia) – jalf

+0

Para la matriz caso es mejor hacer 'str()'. GCC tiene problemas para inicializar la matriz char mediante un literal de cadena a través de un inicializador de miembro, y si la matriz no es una matriz char no funcionará incluso en un compilador conformado estándar. str() 'siempre anulará la matriz. (Acabo de enviar un informe de error: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43453) –

+0

@litb: notado y modificado anteriormente. – rlbond

12

Es una idea terrible. Simplemente está analizando los datos, sin prestar atención a cómo deberían inicializarse los objetos. Si tu clase es virtual, es probable que elimines el puntero vtable también.

memset funciona en datos sin procesar, pero C++ no se trata de datos sin procesar. C++ crea abstracciones, así que si quieres estar seguro usas esas abstracciones. Use la lista de inicializadores para inicializar miembros.

Usted puede hacerlo a tipos de POD:

struct nothing_fancy_here 
{ 
    bool b; 
    int i; 
    void* p; 
}; 

nothing_fancy_here x; 
memset(&x, 0, sizeof(x)); 

Pero si lo estás haciendo en this, que significa que está en un constructor definido por el usuario y ya no califica como un tipo POD . (Aunque si todos sus miembros son POD, podría funcionar, siempre y cuando ninguno contenga 0 como valor de trampa. Estoy seguro de que no estoy seguro si entran en juego otras fuentes de comportamiento indefinido.)

+0

¿Su tipo 'nothing_fancy_here' también tiene un constructor? No creo que haya ninguna diferencia entre lo que está llamando un tipo de POD, y la clase de ejemplo de OP ... Ya sea que llame a 'memset' dentro del constructor o no es irrelevante. Si está bien en tu ejemplo, está bien en los OP. –

+0

@STingRay: no tiene constructor. Tal vez el '// ...' es demasiado abierto. – GManNickG

+0

Tiene un constructor. De acuerdo, es un no-op. El punto acerca de si hay un constructor explícitamente declarado o no es irrelevante. Lo que importa es, como usted dijo, si la estructura/clase (o cualquiera de los tipos de sus miembros) tiene funciones miembro virtuales. Si el OP no ha declarado un constructor y ha llamado 'memset' tal como lo hizo, no hay diferencia. Entonces, la respuesta final es: en los ejemplos dados, es técnicamente * aceptable * hacer, pero como práctica general, ciertamente no ... –