Malloc vs Nuevo para Primitivos


Entiendo los beneficios de usar new contra malloc en C++. Pero para casos específicos como tipos de datos primitivos (no matriz) - int, float etc., ¿ es más rápido usar malloc que new?

Aunque, siempre es aconsejable usar new incluso para primitivas, si estamos asignando un array para que podamos usar delete[].

Pero para la asignación sin matriz, creo que no habría ninguna llamada de constructor para int? Dado que, el operador new asigna memoria, comprueba si está asignada y luego llama al constructor. Pero solo para primitivas asignación de montón no-matriz, es mejor usar malloc que new?

Por favor avise.

Author: Azeem, 2017-06-16

5 answers

Nunca use malloc en C++. Nunca use new a menos que esté implementando una primitiva de gestión de memoria de bajo nivel.

La recomendación es:

  • Pregúntese: " ¿necesito asignación de memoria dinámica?". Muchas veces puede que no lo necesite - prefiera valores a punteros e intente usar la pila.

  • Si necesita asignación dinámica de memoria, pregúntese "¿quién será el propietario de la memoria/objeto asignados?".

    • Si solo necesita un único propietario (lo cual es muy probable) , debe uso std::unique_ptr. Es una abstracción de coste cero sobre new/delete. (Un desallocador diferente puede ser especificado.)

    • Si necesita propiedad compartida, debe usar std::shared_ptr. Esto es no una abstracción de costo cero, ya que utiliza operaciones atómicas y un "bloque de control" adicional para realizar un seguimiento de todos los propietario.


Si se trata de matrices en particular, la Biblioteca Estándar proporciona dos abstracciones potentes y seguras que no requieren ninguna gestión manual de memoria:

std::array y std::vector debería cubrir el 99% de su " array requiere".


Una cosa más importante: la Biblioteca Estándar proporciona la std::make_unique y std::make_shared que se debe usar siempre para crear instancias de puntero inteligente. Hay algunas buenas razones:

  • Más corto-no hay necesidad de repetir el T (e. g.std::unique_ptr<T>{new T}), no es necesario usar new.

  • Más seguro de excepción. Previenen una posible fuga de memoria causada por la falta de un orden bien definido de evaluación en llamadas a funciones. Por ejemplo,

    f(std::shared_ptr<int>(new int(42)), g())
    

    Podría evaluarse en este orden:

    1. new int(42)
    2. g()
    3. ...

    Si g() lanza, el int se filtra.

  • Más eficiente (en términos de velocidad de ejecución). Esto solo se aplica a std::make_shared - usarlo en lugar de std::shared_ptr directamente permite a la implementación realizar una sola asignación tanto para el objeto como para el bloque de control.

Puede encontrar más información en esta pregunta.

 83
Author: Vittorio Romeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-17 12:26:12

Todavía puede ser necesario usar malloc y free en C++ cuando interactúa con API especificadas usando C simple, porque no garantiza que sea seguro usar free para desasignar memoria asignada con operator new (que es en última instancia lo que usan todas las clases de memoria gestionada), ni usar operator delete para desasignar memoria asignada con malloc.

Un ejemplo típico es POSIX getline (no debe confundirse con std::getline): toma un puntero a un char * variable; esa variable debe apuntar a un bloque de memoria asignado con malloc (o puede ser NULL, en cuyo caso getline llamará a malloc para usted); cuando termine de llamar a getline se espera que llame a free en esa variable.

De manera similar, si está escribiendo una biblioteca, puede tener sentido usar C++ internamente pero definir una API extern "C" para sus llamadores externos, porque eso le brinda una mejor estabilidad de la interfaz binaria e interoperabilidad entre lenguajes. Y si devuelve heap-asignado POD objects a sus llamantes, es posible que desee dejar que desasignen esos objetos con free; no necesariamente pueden usar delete, y hacer que llamen YourLibraryFree cuando no se necesitan operaciones de tipo destructor es no ergonómico.

También puede ser necesario usar malloc cuando implementa objetos contenedores redimensionables, porque no hay equivalente a realloc para operator new.

Pero como dicen las otras respuestas, cuando no tienes este tipo de vinculación de restricciones de interfaz sus manos, utilice una de las clases de memoria gestionada en su lugar.

 26
Author: zwol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-17 15:13:52

Siempre es mejor usar new. Si utiliza malloc todavía tiene que comprobar manualmente si el espacio está asignado.

En c++ moderno se pueden usar punteros inteligentes. Con make_unique y make_shared nunca llamas a new explícitamente. std::unique_ptr no es mayor que el puntero subyacente y la sobrecarga de usarlo es mínima.

 8
Author: Petar Velev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-02 15:23:14

La respuesta a " debería usar new o malloc" es la regla de responsabilidad única .

La gestión de recursos debe hacerse por un tipo que tenga ese único propósito.
Esas clases ya existen, tales como unique_ptr, vector etc.

Usar directamente malloc o new es un pecado capital.

 6
Author: sp2danny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-16 21:58:07

La respuesta de Zwol ya da la respuesta correcta: Use malloc()/free() al interactuar con interfaces C solo.
No voy a repetir esos detalles, voy a responder la pregunta de rendimiento.

La verdad es que el desempeño de malloc() y new puede, y difiere. Cuando realice una asignación con new, la memoria generalmente se asignará a través de una llamada a la función global operator new(), que es distinta de malloc(). Es trivial implemente operator new() llamando a malloc(), pero esto no se hace necesariamente.

De hecho, he visto un sistema donde un operator new() que llama a través de malloc() superaría la implementación estándar de operator new() en aproximadamente 100 ciclos de CPU por llamada. Esa es definitivamente una diferencia medible, y una clara indicación de que la implementación estándar hace algo muy diferente de malloc().

Por lo tanto, si usted está preocupado por el rendimiento, hay tres cosas a do:

  1. Mide tu rendimiento.

  2. Escribe implementaciones de reemplazo para la función global operator new() y sus amigos.

  3. Mida su rendimiento y compare.

Las ganancias/pérdidas pueden o no ser significativas.

 1
Author: cmaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-29 12:50:15