Les personnes qui sont habituées aux langages mal classés sont souvent effrayées par la gestion de la mémoire en C ++. Il existe des outils, comme auto_ptr
et shared_ptr
qui gèrent pour vous de nombreuses tâches de gestion de la mémoire. De nombreuses bibliothèques C ++ sont antérieures à ces outils et ont leur propre manière de gérer les tâches de gestion de la mémoire.
Combien de temps passez-vous sur les tâches de gestion de la mémoire?
Je soupçonne que cela dépend fortement de l'ensemble des bibliothèques que vous utilisez, alors indiquez-nous les bibliothèques auxquelles votre réponse s'applique et indiquez si elles le rendent meilleur ou pire.
Réponses:
Le C ++ moderne ne vous préoccupe pas de la gestion de la mémoire tant que vous n’avez pas à le faire, c’est-à-dire jusqu’à ce que vous deviez organiser votre mémoire à la main, principalement à des fins d’optimisation, ou si le contexte vous y oblige (pensez au matériel à contraintes élevées). J'ai écrit des jeux entiers sans manipuler la mémoire brute, seulement pour utiliser des conteneurs qui sont le bon outil pour le travail, comme dans n'importe quelle langue.
Cela dépend donc du projet, mais la plupart du temps, ce n’est pas une gestion de mémoire que vous devez gérer, mais seulement la durée de vie d’un objet. Ce problème est résolu à l'aide de pointeurs intelligents , l'un des outils C ++ idiomatiques résultant de RAII .
Une fois que vous aurez compris RAII , la gestion de la mémoire ne sera plus un problème.
Ensuite, lorsque vous aurez besoin d'accéder à la mémoire brute, vous le ferez dans un code très spécifique, localisé et identifiable, comme dans les implémentations d'objet de pool, pas "partout".
En dehors de ce type de code, vous n'aurez pas besoin de manipuler la mémoire, mais uniquement des objets à vie.
La partie "difficile" consiste à comprendre RAII.
la source
delete
manuellement, à moins que vous n'ayez une implémentation merdique.return
)La gestion de la mémoire est utilisée pour effrayer les enfants, mais ce n'est qu'un type de ressource qu'un programmeur doit gérer. Pensez aux descripteurs de fichier, aux connexions réseau et aux autres ressources que vous obtenez du système d'exploitation.
Les langages qui prennent en charge la récupération de place ne ignorent généralement pas seulement l'existence de ces ressources, mais rendent également plus difficile leur gestion correcte en ne fournissant pas de destructeur.
En bref, je dirais que les développeurs C ++ ne consacrent pas beaucoup de temps à la gestion de la mémoire. Comme l' indique la réponse de klaim , une fois que vous maîtrisez RAII, le reste n'est que réflexe.
la source
finalize
construction. Cependant, vous ne savez pas quand il sera appelé. Sera-ce avant de manquer de sockets ou d'objets WebResponse? Vous trouverez de nombreux articles qui vous disent que vous ne devriez pas vous en fierfinalize
- avec raison.À peu près aucun. Même avec les anciennes technologies telles que COM, vous pouvez écrire des délimiteurs personnalisés pour les pointeurs standard qui les convertiront très rapidement. Par exemple,
std::unique_ptr
peut être converti pour contenir de manière unique une référence COM avec cinq lignes d’un deleter personnalisé. Même si vous devez écrire manuellement votre propre gestionnaire de ressources, la prévalence de connaissances telles que SRP et copie-échange vous permet d'écrire relativement facilement une classe de gestion de ressources à utiliser pour toujours.En réalité, votre compilateur C ++ 11 est partagé, unique et sans propriété. Il vous suffit d'écrire de petits adaptateurs pour les faire fonctionner même avec du code ancien.
la source
Quand j'étais programmeur C ++ (il y a longtemps), je m'inquiétais longuement du bogue de gestion de la mémoire lorsque j'essayais de le réparer pour en reproduire les bogues .
Avec le modem C ++, la gestion de la mémoire est beaucoup moins un problème, mais pouvez-vous faire confiance à tous les membres d'une grande équipe pour bien faire les choses. Quel est le coût / temps de:
Donc, ce n’est pas seulement le temps passé à « faire », c’est davantage un problème pour les grands projets.
la source
J'utilise beaucoup les bibliothèques boost et TR1, et elles rendent la gestion de la mémoire au sens strict (nouveau / supprimer) non problématique. Par ailleurs, l’allocation de mémoire en C ++ n’est pas bon marché et vous devez faire attention au lieu de création de ces pointeurs partagés de fantaisie. Vous finissez souvent par utiliser des espaces de travail ou à travailler avec de la mémoire en pile. En général, je dirais que c'est principalement un problème de conception, pas un problème de mise en œuvre.
la source
combien de temps cela prend-il en tant que client? très peu, une fois que vous avez compris. quand un conteneur gère la durée de vie et les références, c'est vraiment très simple. imo, c’est beaucoup plus simple que le comptage manuel des références, et il est pratiquement transparent si vous considérez le conteneur que vous utilisez comme une documentation que le compilateur vous empêche commodément d’effectuer des transferts de propriété non valides dans un système typafe bien conçu.
La plupart du temps que je passe (en tant que client) consiste à contenir des types d'autres API, de sorte qu'ils fonctionnent bien dans le contexte de vos programmes. exemple: ceci est mon conteneur ThirdPartyFont, et il prend en charge ces fonctionnalités, et met en œuvre la destruction de cette façon, et la référence à compter de cette façon, et la copie de cette façon, et ... . Bon nombre de ces concepts doivent être en place et c'est souvent l'endroit logique pour les mettre en place. que vous souhaitiez ou non inclure cela en fonction du temps dépend de votre définition (l'implémentation doit exister lors de l'interfaçage avec ces API, de toute façon, non?).
Après cela, vous devrez prendre en compte la mémoire et la propriété. dans un système de niveau inférieur, c'est bien et nécessaire, mais cela peut prendre du temps et un échafaudage pour mettre en œuvre la façon dont vous devriez déplacer les choses. Je ne vois pas cela comme une douleur puisqu'il s'agit d'une exigence d'un système de niveau inférieur. la propriété, le contrôle et la responsabilité sont évidents.
nous pouvons donc orienter cela vers des apis basés sur c qui utilisent des types opaques: nos conteneurs nous permettent d’abstraire tous les détails d’implémentation de la gestion de la durée de vie et de la copie de ces types opaques, ce qui rend finalement la gestion des ressources très simple et permet de gagner du temps, et réduit les implémentations.
leur utilisation est vraiment très simple - le problème (venant de GC) est que vous devez maintenant prendre en compte la durée de vie de vos ressources. Si vous vous trompez, cela peut prendre beaucoup de temps à résoudre. apprendre et intégrer la gestion explicite de la durée de vie est naturellement complexe en comparaison (pas pour tout le monde) - c'est le véritable obstacle. Une fois que vous maîtrisez les durées de vie et que vous utilisez de bonnes solutions, il est très facile de gérer les durées de vie des ressources. ce n'est pas une partie importante de ma journée (à moins qu'un bug difficile ne se soit introduit).
si vous n'utilisez pas de conteneur (pointeur auto / partagé), vous plaidez pour la douleur.
J'ai implémenté mes propres bibliothèques. il me faut du temps pour mettre en œuvre ces choses, mais la plupart des gens les réutilisent (ce qui est généralement une bonne idée).
la source
Vous voulez dire, par exemple, devoir libérer manuellement de la mémoire, fermer des fichiers, etc.? Si tel est le cas, je dirais le minimum et généralement moins que la plupart des autres langues que j'ai utilisées, en particulier si nous généralisons cela non seulement à la "gestion de la mémoire" mais également à la "gestion des ressources". En ce sens, je pense réellement que le C ++ nécessite moins de gestion manuelle des ressources que, disons, Java ou C #.
Cela est principalement dû aux destructeurs qui automatisent la destruction de la ressource (mémoire ou autre). Généralement, le seul moment où je dois libérer / détruire manuellement une ressource en C ++ est si j'implémente une structure de données au niveau vlow (ce que la plupart des gens n'ont pas besoin de faire) ou à l'aide d'une API C où je passe juste un peu de temps encapsulant la ressource C devant être libérée / détruite / fermée manuellement dans un wrapper C ++ conforme à RAII.
Bien sûr, si un utilisateur demande à fermer une image dans un logiciel de retouche d'image, je dois supprimer l'image d'une collection ou quelque chose du genre. Mais espérons que cela ne compte pas comme gestion de "mémoire" ou de "ressources" d'un type qui importe dans ce contexte, car requis dans toutes les langues si vous souhaitez libérer la mémoire associée à cette image à ce moment-là. Mais encore une fois, tout ce que vous avez à faire est de supprimer l’image de la collection et le destructeur d’image s’occupe du reste.
Entre-temps, si je compare à, par exemple, Java ou C #, les utilisateurs sont souvent obligés de fermer des fichiers manuellement, de déconnecter manuellement des sockets, de définir des références d'objet sur null afin de permettre leur ramassage illégal, etc. gestion des ressources dans ces langues si vous me demandez. En C ++, vous n'avez souvent même pas besoin d'
unlock
un mutex manuellement, car le casier à mutex le fait automatiquement pour vous lorsque le mutex sort de son périmètre. Par exemple, vous ne devriez jamais avoir à faire des choses comme celle-ci en C ++:Il n'est pas nécessaire de faire des choses comme fermer des fichiers manuellement en C ++. Ils se ferment automatiquement dès l'instant où ils sortent de la portée, qu'ils le soient par la suite ou par des chemins d'exécution normaux ou exceptionnels. Une chose similaire pour les ressources liées à la mémoire comme
std::vector
. Un tel code, commefile.Close()
ci-dessus, serait souvent mal vu car, en particulier dans le contexte d'unfinally
bloc, cela suggère que la ressource locale doit être libérée manuellement, alors que tout l'état d'esprit autour de C ++ est de l'automatiser.En termes de gestion manuelle de la mémoire, je dirais que le C nécessite le maximum, Java / C # un montant moyen et le C ++ le minimum. Il y a beaucoup de raisons d'être un peu timide en utilisant C ++ car c'est un langage très difficile à maîtriser, mais la gestion de la mémoire ne devrait pas en faire partie. Au contraire, je pense en fait que c'est l'un des langages les plus faciles à utiliser dans cet aspect.
Bien sûr, C ++ vous permet de commencer à allouer manuellement de la mémoire et à appeler
operator delete/delete[]
pour libérer manuellement de la mémoire. Il vous permet également d’utiliser des fonctions C commemalloc
etfree
. Mais ce sont des pratiques de codage à l’ancienne qui, à mon avis, sont devenues obsolètes bien avant que les gens n’en donnent le crédit, puisque Stroustrup prônait RAII avant même d’avoir utilisé ce terme très tôt. Donc, je ne pense même pas qu'il soit juste de dire que "le C ++ moderne" automatise la gestion des ressources, car c'était censé être le but recherché depuis le début. Vous ne pouvez pratiquement pas obtenir une sécurité d'exception autrement. Au début des années 90, de nombreux développeurs malavisés ont essayé d'utiliser le C ++ comme un C avec des objets, ignorant souvent complètement la gestion des exceptions, et il n'a jamais été supposé être utilisé de cette façon. Si vous utilisez le C ++ de la manière dont il était pratiquement destiné à être utilisé, la gestion de la mémoire est totalement automatisée et ne nécessite généralement pas une gestion manuelle (ou devrait être traitée) du tout.la source
Dépend des principaux responsables techniques de l’équipe. Dans certaines entreprises (y compris la mienne), il n’existe pas de concept appelé smart poiner. C'est considéré comme compliqué. Donc, les gens mettent simplement des suppressions partout et il y a un lecteur pour la réparation des fuites de mémoire tous les 2 mois. La nouvelle vague de déclarations de suppression arrive partout. Cela dépend donc de l’entreprise et du type de personnes qui y travaillent.
la source
auto_ptr
et d'amis?