2009-04-30 8 views

Respuesta

70

Contrariamente lo que algunos dicen en sus respuestas, es es posible.

char * c = new char[N](); 

pondrá a cero inicializar todos los personajes (en realidad, se llama valor de inicialización. Sin embargo, el valor de inicialización va a ser cero inicialización para todos los miembros de una matriz de tipo escalar). Si eso es lo que buscas.

Vale la pena señalar que también funciona para (conjuntos de) clase-types sin que el usuario declara constructor en cuyo caso es el valor inicializado cualquier miembro de ellos:

struct T { int a; }; 
T *t = new T[1](); 
assert(t[0].a == 0); 
delete[] t; 

No es cierta extensión o algo así. Funcionó y se comportó de la misma manera en C++ 98 también. Justo allí se llamó inicialización predeterminada en lugar de inicialización de valor. Sin embargo, la inicialización cero se realiza en ambos casos para escalares o matrices de tipos escalares o POD.

+1

¡Aprendo algo nuevo cada día de tus publicaciones! Por cierto, ¿sabes por qué nuevo [N] (42) no está permitido? –

+0

T() es una forma especial: initialization de valor o (lo que era en C++ 98) default-initialization T (42), sin embargo, es inicialización directa, y no funciona para matrices –

+0

Este es el escenario específico Estaba buscando, ¡pero todas estas otras respuestas también son geniales! – nivnad

2

Nope. Siempre inicializará por defecto los elementos asignados, que en el caso de los primitivos no hace nada. Tendrás que hacer un seguimiento con una llamada std :: uninitialized_fill_n o similar.

0

No.Debe cerrarse manualmente la memoria. Recuerde, new no se trata solo de asignar memoria, sino también de inicializar a través de constructores. Aquí es donde calloc es útil en C (que no tiene funciones de inicialización). Puede escribir un contenedor en new o incluso usar calloc, pero la mayoría de las veces para objetos que no sean POD, esto no tiene mucho sentido.

5

Nº Además ni siquiera pensar en hacer algo así:

YourClass *var = new YourClass; 
memset(var, 0, sizeof(YourClass)); 

Usted podría terminar de destrozar su VTABLE (si su clase tiene uno).

Recomendaría usar constructores para borrar la memoria interna (variables) de su clase.

+3

lo sé; si realmente quiere pegarse un tiro en el pie tan mal, ¿es ético detenerlo? :-) –

+0

Definitivamente asigna y establece tu memoria dentro de tu clase. No confíes en Memset. Funciona en muchos casos, pero está "indefinido" en la especificación. –

+0

@McWafflestic: ¡lindo! :-) –

11

No, pero es bastante fácil crear una nueva versión que funcione como calloc. Se puede hacer de la misma manera que se implementa la versión nueva de no-throw.

SomeFile.h

struct zeromemory_t{}; 
extern const zeromemory_t zeromemory; 
void* __cdcel operator new(size_t cbSize, const zeromemory_t&); 

SomeFile.cpp

const zeromemory_t zeromemory; 

void* _cdecl operator new(size_t cbSize, const zeromemory_t&) 
{ 
    void *mem = ::operator new(cbSize); 
    memset(mem,0,cbSize); 
    return mem; 
} 

Ahora se puede hacer lo siguiente para obtener nuevos con la memoria zero'd

MyType* pMyType = new (zeromemory) MyType(); 

Adicionalmente se necesitaría para hacer otras cosas divertidas como definir nuevo [] que es bastante directo también.

+2

Solo para señalar el nombre oficial para esto es la ubicación nueva. Si Danvin quiere más información sobre el tema. También se puede usar para crear cachés de objetos (piense en el caché de losas de Linux kernel) –

+2

s/opeartor/operator /;) Puede que quiera poner como advertencia, asegúrese de crear una instancia de 'const zeromemory_t zeromemory;' en exactamente una unidad de compilación. – ephemient

+0

@ephemient, corrigió el error de ortografía. Curioso, ¿cómo podría incluirse el valor definido en un archivo .cpp en más de una unidad de compilación? – JaredPar

2

Puede hacer una sobrecarga global del operador new y hacer que tome la memoria bruta de calloc(). De esta forma, la memoria se borra antes de que los constructores se puedan ejecutar, por lo que no hay problemas allí.

Cualquier clase que invalide por sí sola no obtendrá su calloc() -basado en new, pero esa clase debería inicializarse correctamente de todos modos.

No se olvide de reemplazar tanto new y delete y las versiones de la matriz ...

Algo así como:

#include <exception> // for std::bad_alloc 
#include <new> 
#include <stdlib.h> // for calloc() and free() 

void* operator new (size_t size) 
{ 
void *p=calloc(size, 1); 
if (p==0) // did allocation succeed? 
    throw std::bad_alloc(); 
return p; 
} 


void operator delete (void *p) 
{ 
free(p); 
} 

void* operator new[] (size_t size) 
{ 
void *p=calloc(size, 1); 
if (p==0) // did allocation succeed? 
    throw std::bad_alloc(); 
return p; 
} 

void operator delete[] (void *p) 
{ 
free(p); 
} 

Tenga en cuenta que estas versiones son bastante simples, no es exactamente lo que debería ser - el operador new debe ejecutarse en un bucle llamando al new_handler (si hay uno instalado) y solo lanzando la excepción bad_alloc si no hay new_handler. O algo así, tendré que buscarlo y actualizarlo más tarde.

Ah, y es posible que desee también anular la versión no_throw también.

+0

¿Qué sucede con las clases que tienen métodos virtuales definidos en este caso? –

+1

No ocurre nada inusual: el constructor se ejecuta normalmente. Es solo que la memoria en bruto en la que trabaja el constructor siempre se borró. –

0

si no insiste en usar new, simplemente puede usar el vector: vector<char> buffer; buffer.resize(newsize); y el contenido se pondrá a cero.

0

Sí.

int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5 

Para las matrices puedes usar algo como memset. Para Windows use ZeroMemory o SecureZeroMemory.

Editar: Consulte la publicación de @lig, que muestra cómo puede inicializar a 0 para matrices utilizando inicialización no directa como la anterior.

+0

try with array - no funcionará (al menos para ISO C++) tal vez algunos compiladores con extensión lo permitan). – Francis

0
class MyClass { 
    public: 
    void* operator new(size_t bytes) { 
     return calloc(bytes, 1); 
    } 
} 

Y puede anular el nuevo operador global si lo desea.

0

Usted puede decir:

vector <char> v(100, 0); 

que crea una matriz contigua de 100 caracteres usando nueva, y se los inicializa a cero. A continuación, puede acceder a la matriz con el operador del vector [], o haciendo:

char * p = &v[0]; 
p[3] = 42; 

Nota esto también le libera de tener que llamar a borrar para liberar la memoria asignada.

1

i utiliza una macro:

#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE(); 

utilizarlo:

Whatever* myWhatever = newclear(Whatever); 

(este utiliza "colocación nueva" como algunas otras soluciones aquí)

+0

no olvide el # antes de definir: D (aparentemente este sitio lo elimina. –

+2

en realidad hay un formato especial para el código fuente. cuatro espacios obtendrán el resaltado especial (ver mi edición). –

Cuestiones relacionadas