pointer new array c++ memory-management malloc new-operator

c++ - array - ¿En qué casos uso malloc vs new?



pointer c++ (18)

A menos que esté obligado a usar C, nunca debe usar malloc . Siempre usa new .

Si necesita una gran cantidad de datos, haga algo como:

char *pBuffer = new char[1024];

Tenga cuidado, aunque esto no es correcto:

//This is incorrect - may delete only one element, may corrupt the heap, or worse... delete pBuffer;

En su lugar, debe hacer esto al eliminar una matriz de datos:

//This deletes all items in the array delete[] pBuffer;

La new palabra clave es la forma C ++ de hacerlo, y se asegurará de que su tipo tenga su constructor llamado . La new palabra clave también es más segura para el tipo, mientras que malloc no es segura para el tipo.

La única forma en que podría pensar que sería beneficioso usar malloc sería si necesitara cambiar el tamaño de su búfer de datos. La new palabra clave no tiene una forma análoga como realloc . La función realloc podría ser capaz de ampliar el tamaño de una parte de la memoria de manera más eficiente.

Vale la pena mencionar que no puede mezclar new / free y malloc / delete .

Nota: Algunas respuestas en esta pregunta no son válidas.

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

Veo en C ++ que hay múltiples formas de asignar y liberar datos y entiendo que cuando llamas a malloc deberías llamar free y cuando usas el new operador debes vincular con delete y es un error mezclar los dos (por ejemplo, llamar free() sobre 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 usted es un experto en C ++, hágame saber cualquier regla general o convenciones que siga a este respecto.


Desde el C ++ FQA Lite :

[16.4] ¿Por qué debería usar malloc () nuevo en lugar de antiguo y confiable?

FAQ: new / delete call the constructor / destructor; nuevo es de tipo seguro, malloc no lo es; Nuevo puede ser anulado por una clase.

FQA: Las virtudes de lo nuevo que se mencionan en las preguntas frecuentes no son virtudes, porque los constructores, los destructores y la sobrecarga de operadores son basura (¿ve qué sucede cuando no tiene recolección de basura?), Y el tipo de problema de seguridad es realmente pequeño aquí (normalmente tiene para convertir el void * devuelto por malloc al tipo de puntero derecho para asignarlo a una variable de puntero con tipo, lo que puede ser molesto, pero lejos de ser "inseguro").

Ah, y el uso de malloc antiguo confiable hace posible usar el realloc igualmente confiable y antiguo. Lástima que no tengamos un nuevo y brillante operador renovar o algo así.

Aún así, lo nuevo no es lo suficientemente malo como para justificar una desviación del estilo común utilizado en un idioma, incluso cuando el lenguaje es C ++. En particular, las clases con constructores no triviales se comportarán mal en formas fatales si simplemente maltrata los objetos. Entonces, ¿por qué no usar nuevos en todo el código? La gente rara vez sobrecarga al operador, por lo que probablemente no se interponga demasiado en tu camino. Y si se sobrecargan de nuevo, siempre puedes pedirles que paren.

Lo siento, simplemente no pude resistirme. :)


Desde una perspectiva más baja, new inicializará toda la memoria antes de proporcionarla, mientras que malloc conservará el contenido original de la memoria.


En el siguiente escenario, no podemos usar nuevo ya que llama al constructor.

class B { private: B *ptr; int x; public: B(int n) { cout<<"B: ctr"<<endl; //ptr = new B; //keep calling ctr, result is segmentation fault ptr = (B *)malloc(sizeof(B)); x = n; ptr->x = n + 10; } ~B() { //delete ptr; free(ptr); cout<<"B: dtr"<<endl; } };


Hay algunas cosas que hace new que malloc no hace:

  1. new construye el objeto llamando al constructor de ese objeto
  2. new no requiere encasillado de la memoria asignada.
  3. No requiere que se asigne una cantidad de memoria, sino que requiere que se construyan varios objetos.

Por lo tanto, si usa malloc , entonces debe hacer lo anterior explícitamente, lo que no siempre es práctico. Además, lo new puede estar sobrecargado, pero malloc no puede estarlo.


Hay una gran diferencia entre malloc y new . malloc asigna memoria. Esto está bien para C, porque en C, un bulto 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 que realmente tenga un objeto allí. Los tipos no POD son muy comunes en C ++, ya que muchas características de C ++ hacen que un objeto no sea POD automáticamente.

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:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

El puntero que obtiene no se puede anular debido a que no apunta a un objeto. Necesitaría llamar a un constructor en él antes de poder usarlo (y esto se hace usando una new ubicación).

Si, por otro lado, haces:

non_pod_type* p = new non_pod_type();

Obtienes un puntero que siempre es válido, porque un new objeto creado.

Incluso para los tipos de POD, hay una diferencia significativa entre los dos:

pod_type* p = (pod_type*) malloc(sizeof *p); std::cout << p->foo;

Este fragmento de código imprimiría un valor no especificado, porque los objetos POD creados por malloc no se inicializan.

Con el new , podría especificar un constructor al que llamar, y así obtener un valor bien definido.

pod_type* p = new pod_type(); std::cout << p->foo; // prints 0

Si realmente lo desea, puede usar el uso new para obtener objetos POD sin inicializar. Vea esta otra respuesta para más información sobre eso.

Otra diferencia es el comportamiento ante el fracaso. Cuando no se puede asignar memoria, malloc devuelve un puntero nulo, mientras que el new lanza una excepción.

El primero requiere que pruebe cada puntero devuelto antes de usarlo, mientras que el último siempre generará punteros válidos.

Por estas razones, en el código C ++ debe usar new , y no malloc . Pero incluso en ese caso, no debe usar el new "en abierto", ya que adquiere los recursos que necesita liberar más adelante. Cuando use new , debe pasar su resultado inmediatamente a una clase de gestión de recursos:

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won''t leak


La respuesta corta es: no use malloc para C ++ sin una buena razón para hacerlo. malloc tiene una serie de deficiencias cuando se utiliza con C ++, que se definió para superar.

Deficiencias arregladas por nuevo para el código C ++

  1. Malloc no es seguro para los tipos de ninguna manera significativa. En C ++ se requiere que emita el retorno de void* . Esto potencialmente introduce muchos problemas:

    #include <stdlib.h> struct foo { double d[5]; }; int main() { foo *f1 = malloc(1); // error, no cast foo *f2 = static_cast<foo*>(malloc(sizeof(foo))); foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad }

  2. Aunque es peor que eso. Si el tipo en cuestión es POD (datos antiguos), entonces puede usar semi-sensiblemente malloc para asignar memoria, como hace f2 en el primer ejemplo.

    No es tan obvio, sin embargo, si un tipo es POD. El hecho de que es posible que un tipo dado cambie de POD a no POD sin un error de compilación resultante y potencialmente muy difícil de solucionar problemas es un factor importante. Por ejemplo, si alguien (posiblemente otro programador, durante el mantenimiento, mucho más tarde realizaría un cambio que causó que foo ya no fuera POD, entonces no aparecería un error obvio en el momento de la compilación como esperaría, por ejemplo:

    struct foo { double d[5]; virtual ~foo() { } };

    haría que el malloc de f2 también se vuelva malo, sin ningún diagnóstico obvio. El ejemplo aquí es trivial, pero es posible introducir accidentalmente el non-PODness mucho más lejos (por ejemplo, en una clase base, agregando un miembro no-POD). Si tiene C ++ 11 / boost puede usar is_pod para verificar que esta suposición es correcta y generar un error si no lo es:

    #include <type_traits> #include <stdlib.h> foo *safe_foo_malloc() { static_assert(std::is_pod<foo>::value, "foo must be POD"); return static_cast<foo*>(malloc(sizeof(foo))); }

    Aunque boost no puede determinar si un tipo es POD sin C ++ 11 o algunas otras extensiones de compilador.

  3. malloc devuelve NULL si la asignación falla. new lanzará std::bad_alloc . El comportamiento del uso posterior de un puntero NULL no está definido. Una excepción tiene una semántica limpia cuando se lanza y se emite desde la fuente del error. Envolver malloc con una prueba adecuada en cada llamada parece tedioso y propenso a errores. (Solo tienes que olvidar una vez para deshacer todo ese buen trabajo). Se puede permitir que una excepción se propague a un nivel en el que una persona que llama pueda procesarla con sensatez, donde NULL es mucho más difícil de devolver de manera significativa. Podríamos extender nuestra función safe_foo_malloc para lanzar una excepción o salir del programa o llamar a algún controlador:

    #include <type_traits> #include <stdlib.h> void my_malloc_failed_handler(); foo *safe_foo_malloc() { static_assert(std::is_pod<foo>::value, "foo must be POD"); foo *mem = static_cast<foo*>(malloc(sizeof(foo))); if (!mem) { my_malloc_failed_handler(); // or throw ... } return mem; }

  4. Fundamentalmente, malloc es una característica de C y la new es una característica de C ++. Como resultado, malloc no juega bien con los constructores, solo se ve asignando una porción de bytes. Podríamos extender nuestro safe_foo_malloc más para usar la ubicación new :

    #include <stdlib.h> #include <new> void my_malloc_failed_handler(); foo *safe_foo_malloc() { void *mem = malloc(sizeof(foo)); if (!mem) { my_malloc_failed_handler(); // or throw ... } return new (mem)foo(); }

  5. Nuestra función safe_foo_malloc no es muy genérica; lo ideal es que queramos algo que pueda manejar cualquier tipo, no solo foo . Podemos lograr esto con plantillas y plantillas variadas para constructores no predeterminados:

    #include <functional> #include <new> #include <stdlib.h> void my_malloc_failed_handler(); template <typename T> struct alloc { template <typename ...Args> static T *safe_malloc(Args&&... args) { void *mem = malloc(sizeof(T)); if (!mem) { my_malloc_failed_handler(); // or throw ... } return new (mem)T(std::forward(args)...); } };

    Ahora, aunque al solucionar todos los problemas que hemos identificado hasta ahora, prácticamente hemos reinventado el new operador predeterminado. Si vas a usar malloc y la new ubicación, entonces, ¡podrías comenzar con la new !


Los operadores new y delete pueden operar en clases y estructuras, mientras que malloc y free solo funcionan con bloques de memoria que deben ser lanzados.

El uso de new/delete ayudará a mejorar su código, ya que no necesitará convertir la memoria asignada a la estructura de datos requerida.


Para responder a su pregunta, debe saber la diferencia entre malloc y new . La diferencia es simple:

malloc asigna memoria , mientras que new asigna memory AND llama al constructor del objeto para el que está asignando la memoria.

Por lo tanto, 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 tu programa.

También la diferencia entre free y delete es la misma. La diferencia es que delete llamará al destructor de su objeto además de liberar memoria.


Si tiene el código C que desea trasladar a C ++, puede dejar cualquier llamada malloc () en él. Para cualquier código nuevo de C ++, recomiendo usar un nuevo en su lugar.


Si trabaja con datos que no requieren construcción / destrucción y requiere reasignaciones (por ejemplo, una gran variedad de entradas), creo que malloc / free es una buena opción, ya que le proporciona realloc, que es mucho más rápido que new-memcpy -eliminar (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 debería usar ambos (siempre que libere su memoria maliciosa y elimine los objetos asignados con nuevos) si puede aprovechar el aumento de velocidad (a veces uno significativo, si está reasignando matrices grandes) de POD) que realloc te puede dar.

Sin embargo, a menos que lo necesites, debes mantenerte en nuevo / eliminar en C ++.


Siempre use nuevo en C ++. Si necesita un bloque de memoria sin tipo, puede usar el operador new directamente:

void *p = operator new(size); ... operator delete(p);


Un caso raro para considerar usar malloc / free en lugar de new / delete es cuando asignas y luego reasignas (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 más c ++ enfoque)


Utilice malloc y free solo para asignar memoria que será administrada por bibliotecas y APIs centradas en c. Use new y delete (y las [] variantes) para todo lo que controle.


malloc () se utiliza para asignar dinámicamente memoria en C, mientras que new () realiza el mismo trabajo en c ++. Así que no puedes mezclar convenciones de codificación de 2 idiomas. Sería bueno si pidieras una diferencia entre calloc y malloc ()


si está utilizando c ++, intente usar new / delete en lugar de malloc / calloc, ya que son operadores en sí mismos en comparación con malloc / calloc. Para ellos, solía incluir otro encabezado para eso. No mezcle dos idiomas diferentes en una sola codificación. .su trabajo es similar en todos los aspectos, ya que ambos asignan la memoria dinámicamente del segmento de pila en la tabla hash.


new inicializará los valores predeterminados de la estructura y vinculará correctamente las referencias en sí mismo.

P.ej

struct test_s { int some_strange_name = 1; int &easy = some_strange_name; }

Así que new struct test_s devolverá una estructura inicializada con una referencia de trabajo, mientras que la versión de malloc''ed no tiene valores predeterminados y las referencias internas no se inicializan.


nuevo vs malloc ()

1) new es un operador , mientras que malloc() es una función .

2) new constructores de llamadas, mientras que malloc() no lo hace.

3) new devuelve el tipo de datos exacto , mientras que malloc() devuelve void * .

4) new nunca devuelve un valor NULL (se producirá un error), mientras que malloc() devuelve un valor nulo

5) La reasignación de memoria no es manejada por new mientras malloc() puede