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.
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 sobrenew
/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<T, N>
: una matriz fija deN
de elementos de tipoT
.std::vector<T>
: un array redimensionable de elementos de tipoT
.
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 usarnew
.-
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:
new int(42)
-
g()
- ...
Si
g()
lanza, elint
se filtra. Más eficiente (en términos de velocidad de ejecución). Esto solo se aplica a
std::make_shared
- usarlo en lugar destd::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.
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.
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.
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.
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:
Mide tu rendimiento.
Escribe implementaciones de reemplazo para la función global
operator new()
y sus amigos.Mida su rendimiento y compare.
Las ganancias/pérdidas pueden o no ser significativas.
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