resueltos - manejo de memoria en c++
C++: ¿nueva llamada que se comporta como calloc? (11)
¿Hay alguna llamada que pueda hacer a calloc
new
para que ponga a cero la memoria como calloc
?
Al contrario de lo que algunos dicen en sus respuestas, es posible.
char * c = new char[N]();
Va a inicializar cero todos los caracteres (en realidad, se llama inicialización de valor. Pero la inicialización de valor va a ser inicialización cero para todos sus miembros de una matriz de tipo escalar). Si eso es lo que buscas.
Vale la pena notar que también funciona para (matrices de) tipos de clase sin el constructor declarado por el usuario en cuyo caso cualquier miembro de ellos tiene un valor inicializado:
struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;
No es una 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.
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 puede hacer lo siguiente para obtener información nueva con memoria cero
MyType* pMyType = new (zeromemory) MyType();
Además, necesitarías hacer otras cosas divertidas como definir nuevo [], lo cual es bastante sencillo también.
No. Tampoco pienses en hacer algo como:
YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
Podrías terminar destrozando tu VTABLE (si tu clase tiene uno).
Recomendaría usar constructores para borrar la memoria interna (variables) de su clase.
No. Tienes que poner a cero manualmente la memoria. Recuerde, lo 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 new
o incluso usar el calloc
, pero la mayoría de las veces para objetos que no sean POD, esto no tiene mucho sentido.
Nop. 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.
Podría hacer una sobrecarga global de 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 sobrescribe nueva por sí sola no obtendrá su especial basado en calloc()
, pero esa clase debería inicializarse correctamente de todos modos.
No olvides anular las versiones new
y delete
y las de la matriz ...
Algo 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 simples no son exactamente lo que deberían ser: el new
operador debería ejecutarse en un bucle llamando a new_handler
(si hay uno instalado) y lanzando solo 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 anular también la versión no_throw
.
Puedes decir:
vector <char> v( 100, 0 );
que crea una matriz contigua de 100 caracteres usando new, y los inicializa a cero. A continuación, puede acceder a la matriz con el operador vector [], o haciendo:
char * p = &v[0];
p[3] = 42;
Tenga en cuenta que esto también le libera de tener que llamar borrar para liberar la memoria asignada.
Sí.
int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5
Para arreglos puedes usar algo como memset. Para Windows use ZeroMemory o SecureZeroMemory.
Editar: Consulte la publicación de @ litb, que muestra cómo puede inicializar a 0 para matrices utilizando la inicialización no directa como se indicó anteriormente.
si no insistes en usar new
, simplemente puedes usar vector: vector<char> buffer; buffer.resize(newsize);
vector<char> buffer; buffer.resize(newsize);
y el contenido se pondrá a cero.
yo uso una macro:
#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();
para usarlo:
Whatever* myWhatever = newclear(Whatever);
(Esto usa "colocación nueva" como algunas otras soluciones aquí)
class MyClass {
public:
void* operator new(size_t bytes) {
return calloc(bytes, 1);
}
}
Y puede anular el nuevo operador global si lo desea.