¿En qué casos uso malloc y / o nuevo?

479

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.

JVApen
fuente
33
Solo me gustaría agregar un recordatorio de que no puede mezclar los dos estilos, es decir, no puede usar new para crear un objeto y luego llamar a free (), ni intentar eliminar un bloque asignado por malloc (). Probablemente obvio decirlo, pero sin embargo ...
nsayer
32
Buenas respuestas, todo lo que tengo que agregar (que no he visto) es que new / delete llama al constructor / destructor por ti, malloc / free no. Solo una diferencia que vale la pena mencionar.
Bill K
Con C ++ moderno, todavía estoy tratando de encontrar una razón para usar cualquiera.
Rahly
O no use ninguno y vaya con std: shared_ptr <T>. Entonces no tienes que eliminar nada.
Vincent

Respuestas:

387

A menos que se vea obligado a usar C, nunca debe usarlomalloc . Siempre uso new.

Si necesita una gran cantidad de datos, simplemente 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 newpalabra clave es la forma C ++ de hacerlo, y se asegurará de que su tipo tenga su constructor llamado . La newpalabra clave también es más segura para escribir, mientras mallocque 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. La newpalabra clave no tiene una forma análoga como realloc. La reallocfunció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/ freey 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
Brian R. Bondy
fuente
2
Con respecto a llamar a delete foo cuando debe llamar a delete [] foo, algunos compiladores lo solucionarán automáticamente y no perderán, y otros solo eliminarán la primera entrada y la pérdida. Tenía algunos de estos en algún código y valgrind los encontrará por usted.
KPexEA
30
Si no utiliza la eliminación correcta, el resultado no está definido . Es incorrecto El hecho de que a veces pueda hacer que algo funcione bien o que funcione es simplemente una suerte ciega.
Michael Burr
8
@KPexEA: Incluso si algunos compiladores pueden corregir sus errores, sigue siendo un error cometerlos en primer lugar :) Siempre use eliminar [] cuando corresponda.
korona
6262
"A menos que se vea obligado a usar C, nunca debe usar malloc. Siempre use uno nuevo". ¿Por qué? ¿Cuál es la victoria aquí? Para los objetos que necesitamos construcción, pero para los bloques de memoria, documenta claramente dos formas de cometer errores de codificación (la más fácil de capturar () frente a [] en la nueva y la matriz mal emparejada menos fácilmente capturada frente al escalador nuevo y eliminar). ¿Cuál es la motivación para usar new / delete para bloques de memoria sin formato?
Ben Supnik
3
@DeadMG: Si uno está creando una matriz para su uso por una función API asincrónica, ¿no new[]sería mucho más seguro que std::vector? Si se usa new[], la única forma en que el puntero se volvería inválido sería a través de explícito delete, mientras que la memoria asignada para un std::vectorpodría invalidarse cuando el vector cambia de tamaño o deja el alcance. (Tenga en cuenta que cuando se usa new[]uno debería permitir la posibilidad de que uno no pueda llamar deletesi 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) .
supercat
144

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 ++, que newse definió para superar.

Deficiencias corregidas por nuevo para código C ++

  1. mallocno es seguro de tipo de ninguna manera significativa. En C ++ se requiere que eches el retorno desde void*. Potencialmente, esto 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. 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 lo f2hace 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:

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

    haría que el mallocde f2tambié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í:

    #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 el impulso es no puede determinar si un tipo es POD sin C ++ 11 u otras extensiones del compilador.

  3. mallocdevuelve NULLsi la asignación falla. newarrojará std::bad_alloc. El comportamiento de utilizar un NULLpuntero posteriormente no está definido. Una excepción tiene una semántica limpia cuando se genera y se genera desde la fuente del error. Ajustar malloccon 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, donde NULLes mucho más difícil transmitirla de manera significativa. Podríamos extender nuestra safe_foo_mallocfunción 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 malloces una característica de C y newes una característica de C ++. Como resultado malloc, no funciona bien con los constructores, solo se trata de asignar una porción de bytes. Podríamos extender nuestra safe_foo_mallocubicación para usarnew :

    #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 safe_foo_malloc función no es muy genérica, idealmente queremos 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 identificamos hasta ahora, prácticamente hemos reinventado el newoperador predeterminado . Si va a usar mallocy colocar new, ¡podría usarlo newpara comenzar!

Flexo
fuente
27
Está muy mal hecho C ++ structy classsignifica básicamente lo mismo; Me pregunto si habría habido problemas al structestar reservado para los POD y posiblemente se suponga que todos los classtipos 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 en structlugar de class?
supercat
1
@supercat Un poco tarde, pero resulta que hacer structy classhacer casi lo mismo fue una decisión de diseño maravillosa que ahora permite una característica ordenada llamada "metaclases" (de Herb) .
Rakete1111
@ Rakete1111: A primera vista, parece que esa propuesta procesa previamente una versión del lenguaje que usa palabras clave con prefijo en dólares como $class. Sin embargo, no estoy seguro de qué tiene que ver eso classy structser sinónimos.
supercat
@supercat El sistema de tipos se habría bifurcado más. Al tener classy structmedia efectivamente lo mismo, se puede hacer transformaciones arbitrarias de ellos ( $class) sin tener que preocuparse de hacer una classuna structy viceversa.
Rakete1111
@ Rakete1111: Si ciertos tipos de operaciones y transformaciones son seguras con algunos tipos pero no con otros, hacer que el tipo lo identifique directamente y que un compilador rechace las operaciones y transformaciones inseguras, parecería mejor que tener un cambio en una metaclase que se utilizó en las formas que solo son adecuadas para un PODS, se cambian silenciosamente a no PODS.
supercat
53

Del C ++ FQA Lite :

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

Preguntas frecuentes: nuevo / eliminar llame al constructor / destructor; nuevo es de tipo seguro, malloc no lo es; nuevo puede ser anulado por una clase.

FQA: Las virtudes de los nuevos mencionados en las Preguntas frecuentes no son virtudes, porque los constructores, los destructores y la sobrecarga del operador son basura (¿ves lo que sucede cuando no tienes recolección de basura?), Y el problema de seguridad tipo es realmente pequeño aquí (normalmente tienes para emitir el vacío * devuelto por malloc al tipo de puntero derecho para asignarlo a una variable de puntero tipeado, que puede ser molesto, pero lejos de ser "inseguro").

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

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

Lo siento, no pude resistirme. :)

Matthias Benkard
fuente
77
Eso es un motín ! Gracias.
dmckee --- ex-gatito moderador
8
No puedo tomar en serio este comentario, ya que claramente proyecta la parcialidad del autor contra C ++. C ++ es un lenguaje utilizado para crear software orientado al rendimiento, y un recolector de basura solo podría ser perjudicial para su objetivo. No estoy de acuerdo con tu respuesta completa!
Miguel
1
@Miguel Te perdiste el chiste.
Dan Bechard el
50

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);
Ferruccio
fuente
3
interesante, siempre asigné una matriz de caracteres sin signo cuando necesito un búfer de datos sin formato como este.
Greg Rogers
Cuidado, la semántica debería ser así: p_var = nuevo tipo (inicializador); No tamaño
Brian R. Bondy
11
No, si llama al operador nuevo directamente, entonces se necesita la cantidad de bytes para asignar como parámetro.
Ferruccio
1
No estoy seguro, nunca he oído hablar de esta sintaxis.
Brian R. Bondy
99
Lo contrario de operator newes operator delete. No es una acción bien definida invocar deleteuna expresión con tipo void*.
CB Bailey
33

Ú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.free newdelete[]

dmckee --- gatito ex moderador
fuente
10
Observe también que una biblioteca C bien escrita ocultará malloc y la liberará internamente, así es como debería funcionar el programador C.
Dacav
@dmckee ¿tiene un ejemplo de C ++ usando bibliotecas centradas en c de malloc y gratis?
milesma
1
@Dacav: si una función C aceptará un puntero a un objeto que necesitará seguir usando después de que la función regrese, y la persona que llama no tendrá forma de saber cuándo el objeto todavía es necesario, sería perfectamente razonable para la función para especificar que el puntero debe haberse creado con malloc. Del mismo modo, si una función como strdupnecesita crear un objeto y devolverlo a la persona que llama, es perfectamente razonable especificar que la persona que llama debe llamar freeal objeto cuando ya no se necesita. ¿Cómo podrían tales funciones evitar exponer su uso de malloc / free a la persona que llama?
supercat
@supercat, hay algo inherentemente incorrecto en hacer que una función C acepte un puntero a objetos, ya que C no tiene conocimiento de los objetos en absoluto. En general, creo que el mejor enfoque es tener envolturas semánticas alrededor de la asignación / desasignación también en C. Puede ser aceptable, pero menos flexible, si una biblioteca C le está pidiendo a la persona que llama preasignar y / o desasignar memoria. Si una función C está haciendo esto y reclama la propiedad en la memoria asignada, se le requiere implícitamente asignarla con malloc.
Dacav
@supercat Un ejemplo de un paquete diario que estoy seguro de que todos han usado es libgmp. Si alguna vez usó algún cifrado de código abierto o software basado en dicho cifrado (lo cual es muy probable), entonces probablemente haya utilizado una biblioteca aritmética de precisión arbitraria que necesita crecer y reducir sus propios datos internos. Esto se hace usando una función de inicialización ... y luego tienes que preguntarte, ¿cómo usas el código C que es libgmp, en C ++, sin recompilarlo en C ++? Ahora con eso (el enlazador) en mente, piénselo ... ¿por qué alguna persona sensata alguna vez pondría mallocen C ++?
autista
31

nuevo vs malloc ()

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

2) newllama a los constructores , mientras malloc()que no.

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

4) newnunca devuelve un NULL (arrojará en caso de falla) mientras que malloc()devuelve NULL

5) Reasignación de memoria no manejada newmientras malloc()puede

Yogeesh HT
fuente
66
Hola, para el punto 4), nuevo puede recibir instrucciones de devolver NULL en caso de falla. char* ptr = new (std::nothrow) char [323232];
Singh
1
6) nuevas creaciones a partir de argumentos de constructor, mientras que malloc usa tamaño.
Evan Moran
también hay una newfunción
Ma Ming
Si estuviera tan inclinado en C como para reasignar , espero que use en realloclugar de malloc, y comience con su variable de puntero inicializada en NULL. Si desea una porción de memoria de tamaño variable en C ++, por otro lado, sugeriría std::vectoren lugar de realloc... Eso o un archivo.
autista
19

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

malloc asigna memoria , mientras que new 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 freey deletees bastante la misma. La diferencia es que deletellamará al destructor de su objeto además de liberar memoria.

El físico cuántico
fuente
13

Hay una gran diferencia entre mallocy new.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:

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

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:

non_pod_type* p = new non_pod_type();

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:

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

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.

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

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, mientras newarroja 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 no malloc. Pero incluso entonces, no debe usar new"al aire libre", ya que adquiere recursos que necesita liberar más adelante. Cuando lo 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
R. Martinho Fernandes
fuente
7

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:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

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:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

C ++ 17 también agrega lo std::optionalque puede evitar que requiera asignaciones de memoria

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

Tan pronto como 'instancia' se sale del alcance, la memoria se limpia. Transferir la propiedad también es fácil:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

Entonces, ¿cuándo todavía lo necesitas new? Casi nunca desde C ++ 11 en adelante. La mayoría de las que usa std::make_uniquehasta que llega a un punto en el que alcanza una API que transfiere la propiedad a través de punteros sin procesar.

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

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:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

¡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.

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

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:

  • Está escribiendo una biblioteca estándar con estructuras de datos avanzadas donde malloc es apropiado
  • Tiene que asignar grandes cantidades de memoria (¿En la copia de memoria de un archivo de 10GB?)
  • Tiene herramientas que le impiden usar ciertas construcciones
  • Necesitas almacenar un tipo incompleto
JVApen
fuente
6

Hay algunas cosas que newhace que mallocno:

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

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 pero mallocno se puede.

herohuyongtao
fuente
5

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 ++.

PSkocik
fuente
3

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.

Fred Larson
fuente
3

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.

usuario3488100
fuente
2

new inicializará los valores predeterminados de la estructura y vinculará correctamente las referencias que contiene.

P.ej

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

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.

lama12345
fuente
1

Desde una perspectiva inferior, new inicializará toda la memoria antes de proporcionar la memoria, mientras que malloc mantendrá el contenido original de la memoria.

Peiti Li
fuente
44
En general, new no inicializa la memoria, aunque hay formas de hacer que eso suceda: consulte stackoverflow.com/questions/2204176/… para una discusión al respecto.
wjl
0

En el siguiente escenario, no podemos usar new 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;
    }
};
Barry
fuente
0

Los operadores newy deletepueden operar en clases y estructuras, mientras que mallocy freesolo 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.

selwyn
fuente
0

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 ++).

Florentino Tuason
fuente
-4

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 ()

Hitesh Ahuja
fuente
2
Usted puede (pero casi siempre no debe) utilizar mallocen C ++.
Interjay
1
También se perdió el punto principal de que debe intentar evitar la asignación dinámica de memoria, a menos que lo haga a través de punteros inteligentes. Solo te estás preparando para el dolor de otra manera
thecoshman