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

c++ - bidimensional - Malloc vs New para Primitives



pointer c++ (5)

La respuesta a "debería usar new o malloc " es una sola regla de responsabilidad .

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

Usar directamente malloc o new es un pecado capital.

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

Aunque, siempre es aconsejable usar new incluso para primitivos, si estamos asignando una matriz para que podamos usar delete[] .

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

Por favor avise.


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

La recomendación es:

  • Pregúntese: "¿Necesito una asignación de memoria dinámica?" . Muchas veces puede que no lo necesite; prefiera los valores a los punteros y trate de usar la pila.

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

    • Si solo necesita un único propietario (lo cual es muy probable) , debe usar std::unique_ptr . Es una abstracción de costo cero sobre new / delete . (Se puede especificar un diferente separador).

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

Si se trata de matrices en particular, la biblioteca estándar ofrece dos abstracciones poderosas y seguras que no requieren ninguna gestión de memoria manual:

std::array y std::vector deben cubrir el 99% de sus "necesidades de matriz".

Una cosa más importante: la biblioteca estándar proporciona std::make_unique y std::make_shared que siempre deben usarse para crear instancias de punteros inteligentes. Hay algunas buenas razones:

  • Más corto: no es necesario repetir el T (por ejemplo, std::unique_ptr<T>{new T} ) , no es necesario usar el new .

  • Más excepciones seguras. Impiden una posible pérdida de memoria causada por la falta de un orden de evaluación bien definido en las llamadas a funciones. P.ej

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

    Podría ser evaluado en este orden:

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

    Si g() arroja, el int se filtró.

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

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


Siempre es mejor usar new . Si usa malloc , debe verificarlo manualmente si se asigna espacio.

En el moderno c ++ puedes usar punteros inteligentes. Con make_unique y make_shared nunca llamas new explícita. std::unique_ptr no es más grande que el puntero subyacente y la sobrecarga de su uso es mínima.


Todavía puede ser necesario utilizar malloc y free en C ++ cuando está interactuando con las API especificadas utilizando C simple, porque no se garantiza que sea seguro de utilizar free para desasignar la memoria asignada con el operator new (que es en última instancia lo que todos los administrados uso de clases de memoria), ni para usar el operator delete para desasignar la memoria asignada con malloc .

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

De manera similar, si está escribiendo una biblioteca, puede tener sentido usar C ++ internamente, pero defina una API extern "C" para sus llamadores externos, porque eso le brinda una mejor estabilidad de la interfaz binaria e interoperabilidad entre idiomas. Y si devuelve objetos POD asignados a montones a las personas que llaman, es posible que desee dejarlos desasignar esos objetos de forma free ; no pueden usar necesariamente delete , y hacer que llamen YourLibraryFree cuando no hay operaciones de tipo destructor necesarias es poco ergonómico.

También puede ser necesario utilizar malloc al implementar objetos de contenedor redimensionables, ya que no existe un equivalente de realloc para el operator new .

Pero como dicen las otras respuestas, cuando no tiene este tipo de restricción de interfaz atando sus manos, use una de las clases de memoria administrada.


La respuesta de zwol ya da la respuesta de corrección correcta: use malloc() / free() cuando interactúa solo con las interfaces C.
No voy a repetir esos detalles, voy a responder la pregunta de rendimiento.

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

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

Entonces, si le preocupa el rendimiento, hay tres cosas que puede hacer:

  1. Mida su desempeño.

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

  3. Mida su desempeño y compare.

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