Veo en C ++ que hay varias formas de asignar y liberar datos y entiendo que cuando llame malloc
, debe llamar free
y cuando use el new
operador, debe emparejarse delete
y es un error mezclar los dos (por ejemplo, llamar free()
a algo que se creó con el new
operador), pero no tengo claro cuándo debo usar malloc
/ free
y cuándo debo usar new
/ delete
en mis programas del mundo real.
Si eres un experto en C ++, avísame cualquier regla general o convenciones que sigas al respecto.
c++
memory-management
malloc
new-operator
JVApen
fuente
fuente
Respuestas:
A menos que se vea obligado a usar C, nunca debe usarlo
malloc
. Siempre usonew
.Si necesita una gran cantidad de datos, simplemente haga algo como:
Tenga cuidado, aunque esto no es correcto:
En su lugar, debe hacer esto al eliminar una matriz de datos:
La
new
palabra clave es la forma C ++ de hacerlo, y se asegurará de que su tipo tenga su constructor llamado . Lanew
palabra clave también es más segura para escribir, mientrasmalloc
que no es segura para ningún tipo.La única forma en que podría pensar que sería beneficioso usar
malloc
sería si necesita cambiar el tamaño de su búfer de datos. Lanew
palabra clave no tiene una forma análoga comorealloc
. Larealloc
función podría extender el tamaño de un trozo de memoria para usted de manera más eficiente.Vale la pena mencionar que no puedes mezclar
new
/free
ymalloc
/delete
.Nota: Algunas respuestas en esta pregunta no son válidas.
fuente
new[]
sería mucho más seguro questd::vector
? Si se usanew[]
, la única forma en que el puntero se volvería inválido sería a través de explícitodelete
, mientras que la memoria asignada para unstd::vector
podría invalidarse cuando el vector cambia de tamaño o deja el alcance. (Tenga en cuenta que cuando se usanew[]
uno debería permitir la posibilidad de que uno no pueda llamardelete
si el método asincrónico aún está pendiente; si es necesario abandonar una operación asincrónica, es posible que tenga que hacer arreglos para eliminar mediante devolución de llamada) .La respuesta corta es: no use
malloc
para C ++ sin una muy buena razón para hacerlo.malloc
tiene una serie de deficiencias cuando se usa con C ++, quenew
se definió para superar.Deficiencias corregidas por nuevo para código C ++
malloc
no es seguro de tipo de ninguna manera significativa. En C ++ se requiere que eches el retorno desdevoid*
. Potencialmente, esto introduce muchos problemas:Sin embargo, es peor que eso. Si el tipo en cuestión es POD (datos antiguos simples) , puede usarlo de forma semi-sensible
malloc
para asignarle memoria, como lof2
hace en el primer ejemplo.Sin embargo, no es tan obvio si un tipo es POD. El hecho de que sea posible que un tipo determinado cambie de POD a no POD sin que se produzca un error del compilador y potencialmente muy difícil de depurar problemas es un factor significativo. Por ejemplo, si alguien (posiblemente otro programador, durante el mantenimiento, mucho después hiciera un cambio que causó
foo
ya no sea POD, entonces no aparecería ningún error obvio en el momento de la compilación como cabría esperar, por ejemplo:haría que el
malloc
def2
también se vuelva malo, sin ningún diagnóstico obvio. El ejemplo aquí es trivial, pero es posible introducir accidentalmente no PODness mucho más lejos (por ejemplo, en una clase base, agregando un miembro que no sea POD). Si tienes C ++ 11 / boost puedes usaris_pod
para verificar que esta suposición sea correcta y producir un error si no es así:Aunque el impulso es no puede determinar si un tipo es POD sin C ++ 11 u otras extensiones del compilador.
malloc
devuelveNULL
si la asignación falla.new
arrojarástd::bad_alloc
. El comportamiento de utilizar unNULL
puntero posteriormente no está definido. Una excepción tiene una semántica limpia cuando se genera y se genera desde la fuente del error. Ajustarmalloc
con una prueba adecuada en cada llamada parece tedioso y propenso a errores. (Solo tienes que olvidarte una vez para deshacer todo ese buen trabajo). Se puede permitir que una excepción se propague a un nivel en el que la persona que llama pueda procesarla con sensatez, dondeNULL
es mucho más difícil transmitirla de manera significativa. Podríamos extender nuestrasafe_foo_malloc
función para lanzar una excepción o salir del programa o llamar a algún controlador:Fundamentalmente
malloc
es una característica de C ynew
es una característica de C ++. Como resultadomalloc
, no funciona bien con los constructores, solo se trata de asignar una porción de bytes. Podríamos extender nuestrasafe_foo_malloc
ubicación para usarnew
:Nuestra
safe_foo_malloc
función no es muy genérica, idealmente queremos algo que pueda manejar cualquier tipo, no solofoo
. Podemos lograr esto con plantillas y plantillas variadas para constructores no predeterminados:Ahora, aunque al solucionar todos los problemas que identificamos hasta ahora, prácticamente hemos reinventado el
new
operador predeterminado . Si va a usarmalloc
y colocarnew
, ¡podría usarlonew
para comenzar!fuente
struct
yclass
significa básicamente lo mismo; Me pregunto si habría habido problemas alstruct
estar reservado para los POD y posiblemente se suponga que todos losclass
tipos son no POD. Cualquier tipo definido por el código que precedió a la invención de C ++ sería necesariamente POD, por lo que no creo que la compatibilidad con versiones anteriores sea un problema allí. ¿Hay ventajas en tener tipos no PODs declarados como enstruct
lugar declass
?struct
yclass
hacer casi lo mismo fue una decisión de diseño maravillosa que ahora permite una característica ordenada llamada "metaclases" (de Herb) .$class
. Sin embargo, no estoy seguro de qué tiene que ver esoclass
ystruct
ser sinónimos.class
ystruct
media efectivamente lo mismo, se puede hacer transformaciones arbitrarias de ellos ($class
) sin tener que preocuparse de hacer unaclass
unastruct
y viceversa.Del C ++ FQA Lite :
Lo siento, no pude resistirme. :)
fuente
Siempre use nuevo en C ++. Si necesita un bloque de memoria sin tipo, puede usar el operador new directamente:
fuente
operator new
esoperator delete
. No es una acción bien definida invocardelete
una expresión con tipovoid*
.Úselo
malloc
y solo para asignar memoria que será administrada por bibliotecas centradas en c y API. Use y (y las variantes) para todo lo que controle.free
new
delete
[]
fuente
malloc
. Del mismo modo, si una función comostrdup
necesita crear un objeto y devolverlo a la persona que llama, es perfectamente razonable especificar que la persona que llama debe llamarfree
al objeto cuando ya no se necesita. ¿Cómo podrían tales funciones evitar exponer su uso de malloc / free a la persona que llama?malloc
en C ++?nuevo vs malloc ()
1)
new
es un operador , mientras quemalloc()
es una función .2)
new
llama a los constructores , mientrasmalloc()
que no.3)
new
devuelve el tipo de datos exacto , mientras quemalloc()
devuelve void * .4)
new
nunca devuelve un NULL (arrojará en caso de falla) mientras quemalloc()
devuelve NULL5) Reasignación de memoria no manejada
new
mientrasmalloc()
puedefuente
char* ptr = new (std::nothrow) char [323232];
new
funciónrealloc
lugar demalloc
, y comience con su variable de puntero inicializada enNULL
. Si desea una porción de memoria de tamaño variable en C ++, por otro lado, sugeriríastd::vector
en lugar derealloc
... Eso o un archivo.Para responder a su pregunta, debe saber la diferencia entre
malloc
ynew
. La diferencia es simple:malloc
asigna memoria , mientras quenew
asigna memoria Y llama al constructor del objeto para el que está asignando memoria.Entonces, a menos que esté restringido a C, nunca debe usar malloc, especialmente cuando se trata de objetos C ++. Esa sería una receta para romper su programa.
También la diferencia entre
free
ydelete
es bastante la misma. La diferencia es quedelete
llamará al destructor de su objeto además de liberar memoria.fuente
Hay una gran diferencia entre
malloc
ynew
.malloc
asigna memoria. Esto está bien para C, porque en C, un trozo de memoria es un objeto.En C ++, si no está tratando con tipos de POD (que son similares a los tipos de C), debe llamar a un constructor en una ubicación de memoria para tener realmente un objeto allí. Los tipos que no son POD son muy comunes en C ++, ya que muchas características de C ++ hacen que un objeto automáticamente no sea POD.
new
asigna memoria y crea un objeto en esa ubicación de memoria. Para los tipos que no son POD, esto significa llamar a un constructor.Si haces algo como esto:
El puntero que obtiene no se puede desreferenciar porque no apunta a un objeto. Debería llamar a un constructor antes de poder usarlo (y esto se hace mediante la colocación
new
).Si, por otro lado, haces:
Obtiene un puntero que siempre es válido, porque
new
creó un objeto.Incluso para los tipos de POD, hay una diferencia significativa entre los dos:
Este código imprimirá un valor no especificado, porque los objetos POD creados por
malloc
no se inicializan.Con
new
, puede especificar un constructor para llamar, y así obtener un valor bien definido.Si realmente lo desea, puede usar use
new
para obtener objetos POD no inicializados. Vea esta otra respuesta para obtener más información al respecto.Otra diferencia es el comportamiento ante el fracaso. Cuando no puede asignar memoria,
malloc
devuelve un puntero nulo, mientrasnew
arroja una excepción.El primero requiere que pruebe cada puntero devuelto antes de usarlo, mientras que el segundo siempre generará punteros válidos.
Por estas razones, en el código C ++ debe usar
new
, y nomalloc
. Pero incluso entonces, no debe usarnew
"al aire libre", ya que adquiere recursos que necesita liberar más adelante. Cuando lo usenew
, debe pasar su resultado inmediatamente a una clase de gestión de recursos:fuente
La asignación dinámica solo se requiere cuando el tiempo de vida del objeto debe ser diferente del alcance en el que se crea (esto también es válido para hacer que el alcance sea más pequeño y más grande) y tiene una razón específica donde almacenarlo por valor no trabajo.
Por ejemplo:
A partir de C ++ 11, tenemos que
std::unique_ptr
lidiar con la memoria asignada, que contiene la propiedad de la memoria asignada.std::shared_ptr
fue creado para cuando tienes que compartir la propiedad. (necesitará esto menos de lo que esperaría en un buen programa)Crear una instancia se vuelve realmente fácil:
C ++ 17 también agrega lo
std::optional
que puede evitar que requiera asignaciones de memoriaTan pronto como 'instancia' se sale del alcance, la memoria se limpia. Transferir la propiedad también es fácil:
Entonces, ¿cuándo todavía lo necesitas
new
? Casi nunca desde C ++ 11 en adelante. La mayoría de las que usastd::make_unique
hasta que llega a un punto en el que alcanza una API que transfiere la propiedad a través de punteros sin procesar.En C ++ 98/03, debe hacer una gestión manual de la memoria. Si se encuentra en este caso, intente actualizar a una versión más reciente del estándar. Si estás atrapado:
¡Asegúrese de rastrear la propiedad correctamente para no tener pérdidas de memoria! La semántica de movimiento tampoco funciona todavía.
Entonces, ¿cuándo necesitamos malloc en C ++? La única razón válida sería asignar memoria e inicializarla más tarde mediante la colocación de new.
Aunque lo anterior es válido, esto también se puede hacer a través de un nuevo operador.
std::vector
Es un buen ejemplo de esto.Por último, todavía tenemos el elefante en la habitación:
C
. Si tiene que trabajar con una biblioteca C donde la memoria se asigna en el código C ++ y se libera en el código C (o al revés), se ve obligado a usar malloc / free.Si estás en este caso, olvídate de las funciones virtuales, las funciones miembro, las clases ... Solo se permiten estructuras con PODs.
Algunas excepciones a las reglas:
fuente
Hay algunas cosas que
new
hace quemalloc
no:new
construye el objeto llamando al constructor de ese objetonew
no requiere conversión de tipo de memoria asignada.Entonces, si usa
malloc
, entonces debe hacer las cosas por encima de manera explícita, lo que no siempre es práctico. Además,new
se puede sobrecargar peromalloc
no se puede.fuente
Si trabaja con datos que no necesitan construcción / destrucción y requieren reasignaciones (por ejemplo, una gran variedad de entradas), entonces creo que malloc / free es una buena opción, ya que le brinda realloc, que es mucho más rápido que new-memcpy -delete (está en mi caja de Linux, pero supongo que esto puede depender de la plataforma). Si trabaja con objetos C ++ que no son POD y requieren construcción / destrucción, entonces debe usar los operadores nuevos y eliminar.
De todos modos, no veo por qué no debe usar ambos (siempre que libere su memoria mal asignada y elimine los objetos asignados con nuevos) si puede aprovechar el aumento de velocidad (a veces significativo, si está reasignando matrices grandes de POD) que realloc puede darte.
Sin embargo, a menos que lo necesite, debe apegarse a nuevo / eliminar en C ++.
fuente
Si tiene el código C que desea transferir a C ++, puede dejar cualquier llamada malloc () en él. Para cualquier código C ++ nuevo, recomendaría usar new en su lugar.
fuente
Si está utilizando C ++, intente utilizar new / delete en lugar de malloc / calloc, ya que son operadores. Para malloc / calloc, debe incluir otro encabezado. No mezcle dos idiomas diferentes en el mismo código. Su trabajo es similar en todos los sentidos, ambos asignan memoria dinámicamente desde el segmento de montón en la tabla hash.
fuente
new
inicializará los valores predeterminados de la estructura y vinculará correctamente las referencias que contiene.P.ej
Por
new struct test_s
lo tanto , devolverá una estructura inicializada con una referencia de trabajo, mientras que la versión mal asignada no tiene valores predeterminados y las referencias internas no se inicializan.fuente
Desde una perspectiva inferior, new inicializará toda la memoria antes de proporcionar la memoria, mientras que malloc mantendrá el contenido original de la memoria.
fuente
En el siguiente escenario, no podemos usar new ya que llama al constructor.
fuente
Los operadores
new
ydelete
pueden operar en clases y estructuras, mientras quemalloc
yfree
solo funcionan con bloques de memoria que necesitan ser emitidos.El uso
new/delete
ayudará a mejorar su código, ya que no necesitará convertir la memoria asignada a la estructura de datos requerida.fuente
Un caso raro para considerar el uso de malloc / free en lugar de new / delete es cuando está asignando y luego reasignando (tipos de pod simples, no objetos) usando realloc ya que no hay una función similar a realloc en C ++ (aunque esto se puede hacer usando un Más enfoque C ++).
fuente
malloc () se usa para asignar dinámicamente memoria en C mientras que new () realiza el mismo trabajo en c ++. Por lo tanto, no puede mezclar convenciones de codificación de 2 idiomas. Sería bueno si preguntaras por la diferencia entre calloc y malloc ()
fuente
malloc
en C ++.