¿Hay una llamada que pueda hacer al new
para que tenga cero memoria como calloc
?C++: ¿nueva llamada que se comporta como calloc?
Respuesta
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.
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.
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.
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.
lo sé; si realmente quiere pegarse un tiro en el pie tan mal, ¿es ético detenerlo? :-) –
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. –
@McWafflestic: ¡lindo! :-) –
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.
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) –
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
@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
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.
¿Qué sucede con las clases que tienen métodos virtuales definidos en este caso? –
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ó. –
si no insiste en usar new
, simplemente puede usar el vector: vector<char> buffer; buffer.resize(newsize);
y el contenido se pondrá a cero.
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.
try with array - no funcionará (al menos para ISO C++) tal vez algunos compiladores con extensión lo permitan). – Francis
class MyClass {
public:
void* operator new(size_t bytes) {
return calloc(bytes, 1);
}
}
Y puede anular el nuevo operador global si lo desea.
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.
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í)
no olvide el # antes de definir: D (aparentemente este sitio lo elimina. –
en realidad hay un formato especial para el código fuente. cuatro espacios obtendrán el resaltado especial (ver mi edición). –
- 1. Diccionario observable que no se comporta como se esperaba
- 2. ¿Calloc (4, 6) es lo mismo que calloc (6, 4)?
- 3. Una clase que se comporta como @Entity y @Embeddable
- 4. ¿hay alguna función en java que se comporta como getopt de c
- 5. CSS Estilo Visibilidad no se comporta como se esperaba
- 6. HTML agilidad Paquete removeChild - no se comporta como se esperaba
- 7. jQuery wrapAll no se comporta como se esperaba
- 8. ¿Por qué el readf no se comporta como se esperaba?
- 9. malloc prefiriendo sobre calloc
- 10. Dos argumentos para calloc
- 11. Instancia de MediaPlayer: stop se comporta como una pausa
- 12. Thread.join no se comporta como esperaba en scala
- 13. C pregunta tutorial relacionada con calloc vs malloc
- 14. Android scrollview horizontal se comporta como iPhone (paginación)
- 15. Acción de llamada de nueva llamada entrante
- 16. Android smoothScrollBy se comporta mal
- 17. Folleto: Círculo que se comporta diferente de CircleMarker
- 18. hacer que un objeto se comporta como una matriz para la asignación paralelo en rubí
- 19. Una ventana que se comporta modal y no modalmente
- 20. ¿Jquery append() se comporta de forma asíncrona?
- 21. BASH: [] (prueba) se comporta unconformly
- 22. Estoy muy confundido acerca de malloc() y calloc() en C
- 23. En C, ¿se comporta (x == y == z) lo que yo esperaría?
- 24. BindingList <T> .Sort() se comporta como una lista <T> .Sort()
- 25. ¿Cómo se comporta Verilog con números negativos?
- 26. ¿Un método de clase que se comporta de manera diferente cuando se llama como un método de instancia?
- 27. jQuery selector no se comporta como se esperaba en el HTML analizado de ajax
- 28. ¿Por qué MVC4 @ Styles.Render() no se comporta como se esperaba en el modo de depuración
- 29. instanceof String no se comporta como se esperaba en Google Apps Script
- 30. qué operador de llamada nueva forma explícita
¡Aprendo algo nuevo cada día de tus publicaciones! Por cierto, ¿sabes por qué nuevo [N] (42) no está permitido? –
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 –
Este es el escenario específico Estaba buscando, ¡pero todas estas otras respuestas también son geniales! – nivnad