Las personas que están acostumbradas a los lenguajes recolectados de basura a menudo tienen miedo de la administración de memoria de C ++. Hay herramientas, como auto_ptr
y shared_ptr
que manejarán muchas de las tareas de administración de memoria por usted. Muchas bibliotecas de C ++ son anteriores a esas herramientas y tienen su propia forma de manejar las tareas de administración de memoria.
¿Cuánto tiempo pasas en tareas de administración de memoria?
Sospecho que depende en gran medida del conjunto de bibliotecas que utilice, por lo tanto, indique a qué se aplica su respuesta y si la mejoran o empeoran.
Respuestas:
El C ++ moderno hace que no se preocupe por la administración de la memoria hasta que tenga que hacerlo, es decir, hasta que necesite organizar su memoria a mano, principalmente para fines de optimización, o si el contexto lo obliga a hacerlo (piense en hardware de restricciones grandes). He escrito juegos completos sin manipular la memoria en bruto, solo me preocupa el uso de contenedores que son la herramienta adecuada para el trabajo, como en cualquier idioma.
Por lo tanto, depende del proyecto, pero la mayoría de las veces no es la gestión de la memoria lo que tiene que manejar, sino solo la vida útil del objeto. Eso se resuelve usando punteros inteligentes , que es una herramienta idiomática de C ++ resultante de RAII .
Una vez que comprenda RAII , la administración de memoria no será un problema.
Luego, cuando necesite acceder a la memoria sin procesar, lo hará en un código muy específico, localizado e identificable, como en las implementaciones de objetos de grupo, no "en todas partes".
Fuera de este tipo de código, no necesitará manipular la memoria, solo objetos de por vida.
La parte "difícil" es entender RAII.
fuente
delete
manualmente, a menos que tenga una implementación de mierda.return
)La administración de memoria se usa para asustar a los niños, pero es solo un tipo de recurso que un programador debe cuidar. Piense en los identificadores de archivos, las conexiones de red y otros recursos que obtiene del sistema operativo.
Los lenguajes que admiten la recolección de basura generalmente no solo ignoran la existencia de estos recursos, sino que también hacen que sea más difícil manejarlos adecuadamente al no proporcionar un destructor.
Entonces, en resumen, sugeriría que no se dedique gran parte del tiempo de un desarrollador de C ++ a preocuparse por la administración de la memoria. Como indica la respuesta de klaim , una vez que manejas RAII, el resto es solo reflejo.
fuente
finalize
construcción. Sin embargo, no sabe cuándo se llamará. ¿Será antes de que te quedes sin sockets u objetos de WebResponse? Encontrará muchos artículos que le dicen que no debe confiarfinalize
, con buenas razones.Casi ninguno. Incluso las tecnologías antiguas como COM, puede escribir eliminadores personalizados para los punteros estándar que los convertirán en muy poco tiempo. Por ejemplo,
std::unique_ptr
se puede convertir para mantener de forma exclusiva una referencia COM con cinco líneas de un eliminador personalizado. Incluso si tiene que escribir manualmente su propio manejador de recursos, la prevalencia de conocimientos como SRP y copiar y cambiar hace que sea relativamente fácil escribir una clase de gestión de recursos para usar para siempre.La realidad es que todo lo compartido, único y sin propiedad se entrega con su compilador C ++ 11, y solo tiene que escribir pequeños adaptadores para que funcionen incluso con código antiguo.
fuente
Cuando era un programador de C ++ (hace mucho tiempo), pasé mucho tiempo preocupándome por el error de administración de memoria al tratar de solucionar errores difíciles de reproducir .
Con el módem C ++, la administración de memoria es un problema mucho menor, pero ¿puede confiar en que todos los miembros de un gran equipo lo hagan bien? ¿Cuál es el costo / tiempo de:
Por lo tanto, no se trata solo del tiempo que se dedica a “ hacer ”, sino que se trata más de un problema en grandes proyectos.
fuente
Utilizo mucho las bibliotecas boost y TR1, y hacen que la administración de memoria en sentido estricto (nuevo / eliminar) no sea un problema. Por otro lado, la asignación de memoria en C ++ no es barata, y uno debe prestar atención a dónde se crean estos elegantes punteros compartidos. Terminas usando mucho espacios de trabajo o trabajando con memoria basada en pila. En general, diría que es principalmente un problema de diseño, no un problema de implementación.
fuente
¿Cuánto tiempo lleva como cliente? muy poco, una vez que te acostumbras. cuando un contenedor gestiona la vida útil y las referencias, es realmente muy fácil. OMI, es mucho más simple que el conteo manual de referencias, y es prácticamente transparente si considera el contenedor que usa como documentación que el compilador convenientemente le impide realizar transferencias de propiedad no válidas en un sistema seguro de tipografía bien diseñado.
La mayor parte del tiempo que paso (como cliente) lo paso conteniendo tipos de otras API, por lo que funcionan bien dentro del contexto de sus programas. ejemplo: esta es mi contenedor ThirdPartyFont, y es compatible con estas características, y la destrucción implementos de esta manera, y la referencia a contar de esta manera, y la copia de esta manera, y ... . Muchas de esas construcciones deben estar en su lugar, y a menudo es el lugar lógico para colocarlas. si desea incluir eso como tiempo o no depende de su definición (la implementación debe existir al interactuar con estas API, de todos modos, ¿verdad?).
después de eso, deberá tener en cuenta la memoria y la propiedad. en un sistema de nivel inferior, eso es bueno y necesario, pero puede llevar algo de tiempo y andamiaje implementar cómo debe mover las cosas. No lo veo como un dolor ya que este es un requisito de un sistema de nivel inferior. propiedad, control y responsabilidad son evidentes.
así que podemos orientarlo hacia apis basadas en c que usan tipos opacos: nuestros contenedores nos permiten abstraer todos los pequeños detalles de implementación de la gestión de la vida útil y la copia de esos tipos opacos, lo que en última instancia hace que la gestión de recursos sea muy simple y ahorre tiempo, defectos, y reduce implementaciones.
es realmente muy simple usarlos: el problema (proveniente de GC) es que ahora debe considerar la vida útil de sus recursos. Si se equivoca, puede llevar mucho tiempo resolverlo. El aprendizaje y la integración de la gestión explícita de por vida es comprensiblemente complejo en comparación (no para todas las personas), ese es el verdadero obstáculo. una vez que se sienta cómodo controlando vidas y utilizando buenas soluciones, es realmente muy fácil administrar las vidas de los recursos. No es una parte importante de mi día (a menos que se haya introducido un error difícil).
Si no está utilizando contenedores (puntero automático / compartido), entonces solo está pidiendo dolor.
He implementado mis propias bibliotecas. Me lleva tiempo implementar esas cosas, pero la mayoría de las personas las reutilizan (lo que suele ser una buena idea).
fuente
¿Te refieres a tener que liberar memoria manualmente, cerrar archivos, cosas de este tipo? Si es así, diría que el mínimo y típicamente menos que la mayoría de los otros idiomas que he usado, especialmente si generalizamos eso no solo a la "administración de memoria" sino a la "administración de recursos". En ese sentido, creo que C ++ requiere menos administración de recursos manual que, por ejemplo, Java o C #.
Se debe principalmente a los destructores que automatizan la destrucción del recurso (memoria o no). Por lo general, el único momento en que tengo que liberar / destruir un recurso manualmente en C ++ es si estoy implementando una estructura de datos a nivel de vlow (algo que la mayoría de la gente no necesita hacer) o usando una API de C donde solo paso un poco de tiempo envolviendo el recurso C que necesita ser liberado / destruido / cerrado manualmente en un contenedor C ++ compatible con RAII.
Por supuesto, si un usuario solicita cerrar una imagen en un software de edición de imágenes, tengo que eliminar la imagen de una colección o algo así. Pero, con suerte, eso no cuenta como gestión de "memoria" o "recurso" de un tipo que importa en este contexto, ya que eso es bastante necesario en cualquier idioma si desea liberar la memoria asociada con esa imagen en ese momento. Pero de nuevo, todo lo que tiene que hacer es eliminar la imagen de la colección y el destructor de imágenes se encargará del resto.
Mientras tanto, si me comparo con, por ejemplo, Java o C #, a menudo encuentras personas que tienen que cerrar archivos manualmente allí, desconectar manualmente los sockets, establecer referencias de objeto en nulo para permitir que se recojan basura, etc. Hay mucha más memoria manual y gestión de recursos en esos idiomas si me preguntas. En C ++, a menudo ni siquiera necesita
unlock
un mutex manualmente, ya que el casillero mutex lo hará automáticamente cuando el mutex salga del alcance. Por ejemplo, nunca debería tener que hacer cosas como esta en C ++:No hay necesidad de hacer cosas como cerrar archivos manualmente en C ++. Terminan cerrándose automáticamente en el instante en que salen del alcance, ya sea que se salgan del alcance como resultado o como rutas de ejecución normales o excepcionales. Algo similar para recursos relacionados con la memoria como
std::vector
. Tal código como elfile.Close()
anterior a menudo estaría mal visto, ya que, especialmente en el contexto de unfinally
bloque, sugiere que el recurso local debe liberarse manualmente cuando toda la mentalidad en torno a C ++ es automatizar eso.En términos de gestión de memoria manual, diría que C requiere el máximo, Java / C # una cantidad media y C ++ el mínimo entre estos. Hay muchas razones para ser un poco tímido al usar C ++ ya que es un lenguaje muy difícil de dominar, pero la administración de memoria no debería ser una de ellas. Por el contrario, creo que es uno de los idiomas más fáciles que existen en este aspecto.
Por supuesto, C ++ le permite comenzar a asignar memoria manualmente e invocar
operator delete/delete[]
para liberar memoria manualmente. También le permite usar funciones C comomalloc
yfree
. Pero esas son prácticas de codificación de estilo antiguo que creo que se volvieron obsoletas mucho antes de que las personas den crédito, ya que Stroustrup defendía la RAII incluso antes de que acuñara el término desde el principio. Así que ni siquiera creo que sea justo decir que "C ++ moderno" automatiza la gestión de recursos, porque se suponía que ese era el propósito todo el tiempo. Prácticamente no puede obtener seguridad de excepción de lo contrario. Es solo que muchos desarrolladores equivocados a principios de los 90 intentaron usar C ++ como C con objetos, a menudo ignorando por completo el manejo de excepciones, y nunca se suponía que se usara de esa manera. Si usa C ++ de la forma en que prácticamente siempre se pretendía usar, entonces la administración de memoria está totalmente automatizada y, en general, no es algo con lo que tenga que lidiar manualmente (o debería lidiar) en absoluto.fuente
Depende de los líderes técnicos superiores en el equipo. En algunas empresas (incluida la mía), no existe un concepto llamado puntero inteligente. Se considera elegante. Por lo tanto, la gente simplemente pone eliminaciones por todas partes y hay una unidad para la reparación de pérdidas de memoria por cada 2 meses. Nueva ola de declaraciones de eliminación llegan a todas partes. Entonces, depende de la compañía y del tipo de personas que trabajan allí.
fuente
auto_ptr
y amigos?