Veo en C ++ que hay varias formas de asignar y liberar datos y entiendo que cuando llame malloc, debe llamar freey cuando use el newoperador, debe emparejarse deletey es un error mezclar los dos (por ejemplo, llamar free()a algo que se creó con el newoperador), pero no tengo claro cuándo debo usar malloc/ freey cuándo debo usar new/ deleteen 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
newpalabra clave es la forma C ++ de hacerlo, y se asegurará de que su tipo tenga su constructor llamado . Lanewpalabra clave también es más segura para escribir, mientrasmallocque no es segura para ningún tipo.La única forma en que podría pensar que sería beneficioso usar
mallocsería si necesita cambiar el tamaño de su búfer de datos. Lanewpalabra clave no tiene una forma análoga comorealloc. Lareallocfunció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/freeymalloc/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::vectorpodrí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 llamardeletesi 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
mallocpara C ++ sin una muy buena razón para hacerlo.malloctiene una serie de deficiencias cuando se usa con C ++, quenewse definió para superar.Deficiencias corregidas por nuevo para código C ++
mallocno 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
mallocpara asignarle memoria, como lof2hace 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ó
fooya 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
mallocdef2tambié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_podpara 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.
mallocdevuelveNULLsi la asignación falla.newarrojarástd::bad_alloc. El comportamiento de utilizar unNULLpuntero posteriormente no está definido. Una excepción tiene una semántica limpia cuando se genera y se genera desde la fuente del error. Ajustarmalloccon 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, dondeNULLes mucho más difícil transmitirla de manera significativa. Podríamos extender nuestrasafe_foo_mallocfunción para lanzar una excepción o salir del programa o llamar a algún controlador:Fundamentalmente
malloces una característica de C ynewes 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_mallocubicación para usarnew:Nuestra
safe_foo_mallocfunció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
newoperador predeterminado . Si va a usarmallocy colocarnew, ¡podría usarlonewpara comenzar!fuente
structyclasssignifica básicamente lo mismo; Me pregunto si habría habido problemas alstructestar reservado para los POD y posiblemente se suponga que todos losclasstipos 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 enstructlugar declass?structyclasshacer 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 esoclassystructser sinónimos.classystructmedia efectivamente lo mismo, se puede hacer transformaciones arbitrarias de ellos ($class) sin tener que preocuparse de hacer unaclassunastructy 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 newesoperator delete. No es una acción bien definida invocardeleteuna expresión con tipovoid*.Úselo
mallocy solo para asignar memoria que será administrada por bibliotecas centradas en c y API. Use y (y las variantes) para todo lo que controle.freenewdelete[]fuente
malloc. Del mismo modo, si una función comostrdupnecesita crear un objeto y devolverlo a la persona que llama, es perfectamente razonable especificar que la persona que llama debe llamarfreeal objeto cuando ya no se necesita. ¿Cómo podrían tales funciones evitar exponer su uso de malloc / free a la persona que llama?mallocen C ++?nuevo vs malloc ()
1)
newes un operador , mientras quemalloc()es una función .2)
newllama a los constructores , mientrasmalloc()que no.3)
newdevuelve el tipo de datos exacto , mientras quemalloc()devuelve void * .4)
newnunca devuelve un NULL (arrojará en caso de falla) mientras quemalloc()devuelve NULL5) Reasignación de memoria no manejada
newmientrasmalloc()puedefuente
char* ptr = new (std::nothrow) char [323232];newfunciónrealloclugar 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::vectoren lugar derealloc... Eso o un archivo.Para responder a su pregunta, debe saber la diferencia entre
mallocynew. La diferencia es simple:mallocasigna memoria , mientras quenewasigna 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
freeydeletees bastante la misma. La diferencia es quedeletellamará al destructor de su objeto además de liberar memoria.fuente
Hay una gran diferencia entre
mallocynew.mallocasigna 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.
newasigna 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
newcreó 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
mallocno se inicializan.Con
new, puede especificar un constructor para llamar, y así obtener un valor bien definido.Si realmente lo desea, puede usar use
newpara 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,
mallocdevuelve un puntero nulo, mientrasnewarroja 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_ptrlidiar con la memoria asignada, que contiene la propiedad de la memoria asignada.std::shared_ptrfue 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::optionalque 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_uniquehasta 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::vectorEs 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
newhace quemallocno:newconstruye el objeto llamando al constructor de ese objetonewno 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,newse puede sobrecargar peromallocno 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
newinicializará los valores predeterminados de la estructura y vinculará correctamente las referencias que contiene.P.ej
Por
new struct test_slo 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
newydeletepueden operar en clases y estructuras, mientras quemallocyfreesolo funcionan con bloques de memoria que necesitan ser emitidos.El uso
new/deleteayudará 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
mallocen C ++.