Je vois en C ++ qu'il y a plusieurs façons d'allouer et de libérer des données et je comprends que lorsque vous appelez, malloc
vous devez appeler free
et lorsque vous utilisez l' new
opérateur, vous devez vous associer delete
et c'est une erreur de mélanger les deux (par exemple, appeler free()
quelque chose qui a été créé avec l' new
opérateur), mais je ne sais pas quand je devrais utiliser malloc
/ free
et quand je devrais utiliser new
/ delete
dans mes programmes du monde réel.
Si vous êtes un expert en C ++, veuillez me faire part des règles générales ou des conventions que vous suivez à cet égard.
Réponses:
À moins que vous ne soyez obligé d'utiliser C, vous ne devriez jamais l'utiliser
malloc
. Utilisez toujoursnew
.Si vous avez besoin d'un gros morceau de données, faites simplement quelque chose comme:
Attention, ce n'est pas correct:
Au lieu de cela, vous devez le faire lors de la suppression d'un tableau de données:
Le
new
mot clé est la manière C ++ de le faire, et il s'assurera que votre type aura son constructeur appelé . Lenew
mot-clé est également plus sûr pour le type alors qu'ilmalloc
ne l'est pas du tout.La seule façon dont je pourrais penser qu'il serait avantageux d'utiliser
malloc
serait de changer la taille de votre mémoire tampon de données. Lenew
mot-clé n'a pas de manière analogue commerealloc
. Larealloc
fonction peut être en mesure d'étendre la taille d'un morceau de mémoire plus efficacement pour vous.Il est à noter que vous ne pouvez pas mélanger
new
/free
etmalloc
/delete
.Remarque: certaines réponses à cette question ne sont pas valides.
la source
new[]
beaucoup plus sûr questd::vector
? Si l'on utilisenew[]
, la seule façon dont le pointeur deviendrait invalide serait via explicitedelete
, tandis que la mémoire allouée à anstd::vector
pourrait être invalidée lorsque le vecteur est redimensionné ou quitte la portée. (Notez que lors de son utilisation,new[]
il faudrait prévoir la possibilité que l'on ne puisse pas appelerdelete
si la méthode asynchrone est toujours en attente; s'il peut être nécessaire d'abandonner une opération asynchrone, il faudra peut-être organiser la suppression via un rappel) .La réponse courte est: n'utilisez pas le
malloc
C ++ sans une très bonne raison de le faire.malloc
a un certain nombre de lacunes lorsqu'il est utilisé avec C ++, qui anew
été défini pour surmonter.Défectuosités corrigées par le nouveau code C ++
malloc
n'est pas typé de manière significative. En C ++, vous devez convertir le retour devoid*
. Cela introduit potentiellement beaucoup de problèmes:C'est pire que ça. Si le type en question est POD (plain old data), vous pouvez l'utiliser de manière semi-raisonnable
malloc
pour lui allouer de la mémoire, commef2
dans le premier exemple.Ce n'est pas si évident si un type est POD. Le fait qu'il soit possible pour un type donné de passer de POD à non-POD sans erreur de compilation résultante et potentiellement très difficile à déboguer est un facteur important. Par exemple, si quelqu'un (peut-être un autre programmeur, pendant la maintenance, beaucoup plus tard, apportait une modification qui ne faisait
foo
plus partie du POD, aucune erreur évidente n'apparaissait au moment de la compilation comme vous l'espérez, par exemple:rendrait le
malloc
off2
aussi mauvais, sans aucun diagnostic évident. L'exemple ici est trivial, mais il est possible d'introduire accidentellement un non-PODness beaucoup plus loin (par exemple dans une classe de base, en ajoutant un membre non-POD). Si vous avez C ++ 11 / boost, vous pouvez utiliseris_pod
pour vérifier que cette hypothèse est correcte et produire une erreur si ce n'est pas le cas:Bien que boost ne puisse pas déterminer si un type est POD sans C ++ 11 ou d'autres extensions du compilateur.
malloc
retourneNULL
si l'allocation échoue.new
jetterastd::bad_alloc
. Le comportement de l'utilisation ultérieure d'unNULL
pointeur n'est pas défini. Une exception a une sémantique propre lorsqu'elle est levée et elle est levée à partir de la source de l'erreur. Enveloppermalloc
avec un test approprié à chaque appel semble fastidieux et sujet aux erreurs. (Vous n'avez qu'à oublier une fois pour défaire tout ce bon travail). Une exception peut être autorisée à se propager à un niveau où un appelant est en mesure de le traiter de manière sensible, alors qu'ilNULL
est beaucoup plus difficile de le renvoyer de manière significative. Nous pourrions étendre notresafe_foo_malloc
fonction pour lever une exception ou quitter le programme ou appeler un gestionnaire:Fondamentalement,
malloc
c'est une fonctionnalité C etnew
est une fonctionnalité C ++. En conséquence,malloc
ne fonctionne pas bien avec les constructeurs, il ne regarde que l'allocation d'un morceau d'octets. Nous pourrions étendre notresafe_foo_malloc
utilisation du placementnew
:Notre
safe_foo_malloc
fonction n'est pas très générique - idéalement, nous voudrions quelque chose qui puisse gérer n'importe quel type, pas seulementfoo
. Nous pouvons y parvenir avec des modèles et des modèles variadiques pour les constructeurs non par défaut:Maintenant, cependant, en résolvant tous les problèmes que nous avons identifiés jusqu'à présent, nous avons pratiquement réinventé l'
new
opérateur par défaut . Si vous allez utilisermalloc
et placer,new
vous pourriez tout aussi bien utilisernew
pour commencer!la source
struct
etclass
signifie essentiellement la même chose; Je me demande s'il y aurait eu des problèmes àstruct
être réservé aux POD et à ce que tous lesclass
types soient présumés non-POD. Tous les types définis par du code antérieurs à l'invention du C ++ seraient nécessairement des POD, donc je ne pense pas que la rétrocompatibilité serait un problème. Y a-t-il des avantages à avoir des types non-POD déclarésstruct
plutôt queclass
?struct
etclass
faire presque la même chose a été une merveilleuse décision de conception qui permet désormais une fonctionnalité intéressante appelée "métaclasses" (de Herb) .$class
. Je ne sais pas ce que cela a à voir avecclass
etstruct
étant synonymes, cependant.class
etstruct
signifiant effectivement la même chose, vous pouvez faire des transformations arbitraires sur eux ($class
) sans vous soucier de faire unclass
astruct
et vice-versa.Depuis le C ++ FQA Lite :
Désolé, je n'ai pas pu résister. :)
la source
Utilisez toujours new en C ++. Si vous avez besoin d'un bloc de mémoire non typé, vous pouvez utiliser directement l'opérateur new:
la source
operator new
estoperator delete
. Ce n'est pas une action bien définie d'appelerdelete
une expression de typevoid*
.Utilisez
malloc
et uniquement pour allouer de la mémoire qui sera gérée par les bibliothèques et les API c-centric. Utilisez et (et les variantes) pour tout ce que vous contrôlez.free
new
delete
[]
la source
malloc
. De même, si une fonction comme astrdup
besoin de créer un objet et de le renvoyer à un appelant, il est parfaitement raisonnable de spécifier que l'appelant doit appelerfree
l'objet lorsqu'il n'est plus nécessaire. Comment de telles fonctions pourraient-elles éviter d'exposer leur utilisation de malloc / free à l'appelant?malloc
en C ++?new vs malloc ()
1)
new
est un opérateur , tandis quemalloc()
est une fonction .2)
new
appelle les constructeurs , maismalloc()
pas.3)
new
renvoie le type de données exact , tandis quemalloc()
renvoie void * .4)
new
ne renvoie jamais un NULL (lancera en cas d'échec) tandis quemalloc()
retourne NULL5) Réaffectation de mémoire non traitée par
new
toutmalloc()
bidonla source
char* ptr = new (std::nothrow) char [323232];
new
fonctionrealloc
plutôt quemalloc
, et commencez avec votre variable pointeur initialisées àNULL
. Si vous voulez un morceau de mémoire redimensionnable en C ++, d'un autre côté, je proposerais plutôtstd::vector
querealloc
... ça ou un fichier.Pour répondre à votre question, vous devez connaître la différence entre
malloc
etnew
. La différence est simple:malloc
alloue de la mémoire , tandis quenew
alloue de la mémoire ET appelle le constructeur de l'objet pour lequel vous allouez de la mémoire.Donc, à moins que vous ne soyez limité à C, vous ne devriez jamais utiliser malloc, en particulier lorsque vous traitez avec des objets C ++. Ce serait une recette pour casser votre programme.
La différence entre
free
etdelete
est tout à fait la même. La différence est que vousdelete
appellerez le destructeur de votre objet en plus de libérer de la mémoire.la source
Il y a une grande différence entre
malloc
etnew
.malloc
alloue de la mémoire. C'est très bien pour C, car en C, un morceau de mémoire est un objet.En C ++, si vous ne traitez pas avec des types POD (qui sont similaires aux types C), vous devez appeler un constructeur sur un emplacement mémoire pour y avoir réellement un objet. Les types non-POD sont très courants en C ++, car de nombreuses fonctionnalités C ++ rendent un objet automatiquement non-POD.
new
alloue de la mémoire et crée un objet sur cet emplacement de mémoire. Pour les types non POD, cela signifie appeler un constructeur.Si vous faites quelque chose comme ça:
Le pointeur que vous obtenez ne peut pas être déréférencé car il ne pointe pas vers un objet. Vous devez appeler un constructeur dessus avant de pouvoir l'utiliser (et cela se fait en utilisant le placement
new
).Si, en revanche, vous faites:
Vous obtenez un pointeur qui est toujours valide, car
new
créé un objet.Même pour les types de POD, il existe une différence significative entre les deux:
Ce morceau de code imprimerait une valeur non spécifiée, car les objets POD créés par
malloc
ne sont pas initialisés.Avec
new
, vous pouvez spécifier un constructeur à appeler et ainsi obtenir une valeur bien définie.Si vous le voulez vraiment, vous pouvez utiliser use
new
pour obtenir des objets POD non initialisés. Voir cette autre réponse pour plus d'informations à ce sujet.Une autre différence est le comportement en cas d'échec. Lorsqu'il ne parvient pas à allouer de la mémoire,
malloc
retourne un pointeur nul, tout ennew
lançant une exception.Le premier vous oblige à tester chaque pointeur retourné avant de l'utiliser, tandis que le dernier produira toujours des pointeurs valides.
Pour ces raisons, dans le code C ++, vous devez utiliser
new
et nonmalloc
. Mais même dans ce cas, vous ne devez pas utilisernew
"en plein air", car il acquiert les ressources que vous devez libérer plus tard. Lorsque vous utilisez,new
vous devez transmettre immédiatement son résultat à une classe de gestion des ressources:la source
L'allocation dynamique n'est requise que lorsque la durée de vie de l'objet doit être différente de la portée dans laquelle il est créé (cela vaut également pour rendre la portée plus petite et plus grande) et vous avez une raison spécifique pour laquelle le stockage par valeur ne le fait pas. travail.
Par exemple:
A partir de C ++ 11, nous avons
std::unique_ptr
gérer la mémoire allouée, qui contient la propriété de la mémoire allouée.std::shared_ptr
a été créé lorsque vous devez partager la propriété. (vous en aurez besoin moins que ce à quoi vous vous attendez dans un bon programme)La création d'une instance devient vraiment simple:
C ++ 17 ajoute également
std::optional
ce qui peut vous empêcher d'exiger des allocations de mémoireDès que «instance» sort de la portée, la mémoire est nettoyée. Le transfert de propriété est également simple:
Alors, quand avez-vous encore besoin
new
? Presque jamais à partir de C ++ 11. La plupart de ce que vous utilisezstd::make_unique
jusqu'à ce que vous atteigniez un point où vous atteignez une API qui transfère la propriété via des pointeurs bruts.En C ++ 98/03, vous devez faire une gestion manuelle de la mémoire. Si vous êtes dans ce cas, essayez de mettre à niveau vers une version plus récente de la norme. Si vous êtes coincé:
Assurez-vous de suivre correctement la propriété pour ne pas avoir de fuites de mémoire! Les sémantiques de déplacement ne fonctionnent pas encore non plus.
Alors, quand avons-nous besoin de malloc en C ++? La seule raison valable serait d'allouer de la mémoire et de l'initialiser ultérieurement via placement new.
Même si ce qui précède est valide, cela peut également être fait via un nouvel opérateur.
std::vector
en est un bon exemple.Enfin, nous avons encore l'éléphant dans la pièce:
C
. Si vous devez travailler avec une bibliothèque C où la mémoire est allouée dans le code C ++ et libérée dans le code C (ou l'inverse), vous êtes obligé d'utiliser malloc / free.Si vous êtes dans ce cas, oubliez les fonctions virtuelles, les fonctions membres, les classes ... Seules les structures contenant des POD sont autorisées.
Quelques exceptions aux règles:
la source
Il y a quelques choses qui
new
ne lemalloc
font pas:new
construit l'objet en appelant le constructeur de cet objetnew
ne nécessite pas de transtypage de la mémoire allouée.Donc, si vous utilisez
malloc
, vous devez faire les choses ci-dessus explicitement, ce qui n'est pas toujours pratique. De plus,new
peut être surchargé maismalloc
ne peut pas l'être.la source
Si vous travaillez avec des données qui n'ont pas besoin de construction / destruction et nécessitent des réallocations (par exemple, un grand nombre d'ints), alors je pense que malloc / free est un bon choix car il vous donne une réallocation, qui est beaucoup plus rapide que new-memcpy -delete (c'est sur ma boîte Linux, mais je suppose que cela peut dépendre de la plate-forme). Si vous travaillez avec des objets C ++ qui ne sont pas POD et nécessitent une construction / destruction, vous devez utiliser les opérateurs new et delete.
Quoi qu'il en soit, je ne vois pas pourquoi vous ne devriez pas utiliser les deux (à condition de libérer votre mémoire mallocée et de supprimer les objets alloués avec de nouveaux) si vous pouvez profiter de l'augmentation de vitesse (parfois importante, si vous réaffectez de grands tableaux de POD) que la réaffectation peut vous apporter.
Sauf si vous en avez besoin, vous devez vous en tenir à nouveau / supprimer en C ++.
la source
Si vous avez du code C que vous souhaitez transférer vers C ++, vous pouvez y laisser tous les appels malloc (). Pour tout nouveau code C ++, je recommanderais d'utiliser new à la place.
la source
Si vous utilisez C ++, essayez d'utiliser new / delete au lieu de malloc / calloc car ce sont des opérateurs. Pour malloc / calloc, vous devez inclure un autre en-tête. Ne mélangez pas deux langues différentes dans le même code. Leur travail est similaire à tous égards, les deux allouent de la mémoire dynamiquement à partir du segment de tas dans la table de hachage.
la source
new
initialisera les valeurs par défaut de la structure et liera correctement les références qu'elle contient à elle-même.Par exemple
Donc
new struct test_s
, retournera une structure initialisée avec une référence de travail, tandis que la version malloc'ed n'a pas de valeurs par défaut et les références internes ne sont pas initialisées.la source
D'un point de vue inférieur, new initialisera toute la mémoire avant de donner la mémoire tandis que malloc gardera le contenu original de la mémoire.
la source
Dans le scénario suivant, nous ne pouvons pas utiliser new car il appelle constructeur.
la source
Les opérateurs
new
etdelete
peuvent fonctionner sur les classes et les structures, tandis quemalloc
etfree
ne fonctionnent qu'avec les blocs de mémoire qui doivent être convertis.L'utilisation vous
new/delete
aidera à améliorer votre code car vous n'aurez pas besoin de convertir la mémoire allouée en la structure de données requise.la source
Un cas rare à considérer en utilisant malloc / free au lieu de new / delete est lorsque vous allouez puis réallouez (types de pod simples, pas des objets) en utilisant realloc car il n'y a pas de fonction similaire à realloc en C ++ (bien que cela puisse être fait en utilisant un approche C ++).
la source
malloc () est utilisé pour affecter dynamiquement de la mémoire en C tandis que le même travail est effectué par new () en c ++. Vous ne pouvez donc pas mélanger les conventions de codage de 2 langues. Ce serait bien si vous demandiez la différence entre calloc et malloc ()
la source
malloc
en C ++.