Dans quels cas dois-je utiliser malloc et / ou new?

479

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, mallocvous devez appeler freeet lorsque vous utilisez l' newopérateur, vous devez vous associer deleteet c'est une erreur de mélanger les deux (par exemple, appeler free()quelque chose qui a été créé avec l' newopérateur), mais je ne sais pas quand je devrais utiliser malloc/ freeet quand je devrais utiliser new/ deletedans 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.

JVApen
la source
33
Je voudrais juste ajouter un rappel que vous ne pouvez pas mélanger les deux styles - c'est-à-dire que vous ne pouvez pas utiliser new pour créer un objet puis appeler free () dessus, ni tenter de supprimer un bloc alloué par malloc (). Probablement évident pour le dire, mais néanmoins ...
nsayer
32
Bonnes réponses, tout ce que j'ai à ajouter (que je n'ai pas vu), c'est que new / delete appelle le constructeur / destructeur pour vous, malloc / free ne le fait pas. Juste une différence qui mérite d'être mentionnée.
Bill K
Avec le C ++ moderne, j'essaie toujours de trouver une raison d'utiliser l'un ou l'autre.
Rahly
Ou n'utilisez ni l'un ni l'autre et choisissez std: shared_ptr <T>. Ensuite, vous n'avez pas du tout à supprimer.
Vincent

Réponses:

387

À moins que vous ne soyez obligé d'utiliser C, vous ne devriez jamais l'utilisermalloc . Utilisez toujours new.

Si vous avez besoin d'un gros morceau de données, faites simplement quelque chose comme:

char *pBuffer = new char[1024];

Attention, ce n'est pas correct:

//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;

Au lieu de cela, vous devez le faire lors de la suppression d'un tableau de données:

//This deletes all items in the array
delete[] pBuffer;

Le newmot clé est la manière C ++ de le faire, et il s'assurera que votre type aura son constructeur appelé . Le newmot-clé est également plus sûr pour le type alors qu'il mallocne l'est pas du tout.

La seule façon dont je pourrais penser qu'il serait avantageux d'utiliser mallocserait de changer la taille de votre mémoire tampon de données. Le newmot-clé n'a pas de manière analogue comme realloc. La reallocfonction 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/ freeet malloc/ delete.

Remarque: certaines réponses à cette question ne sont pas valides.

int* p_scalar = new int(5);  // Does not create 5 elements, but initializes to 5
int* p_array  = new int[5];  // Creates 5 elements
Brian R. Bondy
la source
2
En ce qui concerne l'appel de delete foo lorsque vous devez appeler delete [] foo, certains compilateurs corrigeront cela automatiquement pour vous et ne fuiront pas et d'autres ne supprimeront que la première entrée et la première fuite. J'en avais quelques-uns dans du code et valgrind les trouvera pour vous.
KPexEA
30
Si vous n'utilisez pas la suppression correcte, le résultat n'est pas défini . C'est incorrect. Le fait que cela réussisse parfois ou fonctionne parfois n'est qu'une chance aveugle.
Michael Burr
8
@KPexEA: Même si certains compilateurs peuvent corriger vos erreurs, il est toujours faux de les faire en premier lieu :) Utilisez toujours delete [] le cas échéant.
korona
62
"À moins que vous ne soyez obligé d'utiliser C, vous ne devriez jamais utiliser malloc. Utilisez toujours new." Pourquoi? Quelle est la victoire ici? Pour les objets dont nous avons besoin de construction, mais pour les blocs de mémoire, vous documentez clairement deux façons de faire des erreurs de codage (le plus facilement intercepté () vs [] dans le nouveau et le tableau non concordant moins facilement intercepté contre le scaler new et delete). Quelle est la motivation pour utiliser new / delete pour des blocs de mémoire brute?
Ben Supnik
3
@DeadMG: Si l'on crée un tableau à utiliser par une fonction API asynchrone, ne serait-il pas new[]beaucoup plus sûr que std::vector? Si l'on utilise new[], la seule façon dont le pointeur deviendrait invalide serait via explicite delete, tandis que la mémoire allouée à an std::vectorpourrait ê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 appeler deletesi 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) .
supercat
144

La réponse courte est: n'utilisez pas le mallocC ++ sans une très bonne raison de le faire. malloca un certain nombre de lacunes lorsqu'il est utilisé avec C ++, qui a newété défini pour surmonter.

Défectuosités corrigées par le nouveau code C ++

  1. mallocn'est pas typé de manière significative. En C ++, vous devez convertir le retour de void*. Cela introduit potentiellement beaucoup de problèmes:

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
  2. C'est pire que ça. Si le type en question est POD (plain old data), vous pouvez l'utiliser de manière semi-raisonnable mallocpour lui allouer de la mémoire, comme f2dans 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 fooplus partie du POD, aucune erreur évidente n'apparaissait au moment de la compilation comme vous l'espérez, par exemple:

    struct foo {
      double d[5];
      virtual ~foo() { }
    };

    rendrait le mallocof f2aussi 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 utiliser is_podpour vérifier que cette hypothèse est correcte et produire une erreur si ce n'est pas le cas:

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }

    Bien que boost ne puisse pas déterminer si un type est POD sans C ++ 11 ou d'autres extensions du compilateur.

  3. mallocretourne NULLsi l'allocation échoue. newjettera std::bad_alloc. Le comportement de l'utilisation ultérieure d'un NULLpointeur 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. Envelopper mallocavec 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'il NULLest beaucoup plus difficile de le renvoyer de manière significative. Nous pourrions étendre notre safe_foo_mallocfonction pour lever une exception ou quitter le programme ou appeler un gestionnaire:

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
  4. Fondamentalement, mallocc'est une fonctionnalité C et newest une fonctionnalité C ++. En conséquence, mallocne fonctionne pas bien avec les constructeurs, il ne regarde que l'allocation d'un morceau d'octets. Nous pourrions étendre notre safe_foo_mallocutilisation du placement new:

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
  5. Notre safe_foo_mallocfonction n'est pas très générique - idéalement, nous voudrions quelque chose qui puisse gérer n'importe quel type, pas seulement foo. Nous pouvons y parvenir avec des modèles et des modèles variadiques pour les constructeurs non par défaut:

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };

    Maintenant, cependant, en résolvant tous les problèmes que nous avons identifiés jusqu'à présent, nous avons pratiquement réinventé l' newopérateur par défaut . Si vous allez utiliser mallocet placer, newvous pourriez tout aussi bien utiliser newpour commencer!

Flexo
la source
27
C'est dommage que C ++ soit fait structet classsignifie 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 les classtypes 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és structplutôt que class?
supercat
1
@supercat Un peu tard, mais en fin de compte, faire structet classfaire 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) .
Rakete1111
@ Rakete1111: À première vue, cette proposition semble prétraiter une version du langage qui utilise des mots-clés préfixés en dollars comme $class. Je ne sais pas ce que cela a à voir avec classet structétant synonymes, cependant.
supercat
@supercat Le système de type aurait été bifurqué davantage. En ayant classet structsignifiant effectivement la même chose, vous pouvez faire des transformations arbitraires sur eux ( $class) sans vous soucier de faire un classa structet vice-versa.
Rakete1111
@ Rakete1111: Si certains types d'opérations et de transformations sont sûrs avec certains types mais pas avec d'autres, avoir le type l'identifie directement et avoir un compilateur rejeter les opérations et les transformations non sécurisées, semble préférable à la modification d'une métaclasse utilisée dans les moyens qui ne conviennent qu'à un PODS, deviennent silencieusement remplacés par des non-PODS.
supercat
53

Depuis le C ++ FQA Lite :

[16.4] Pourquoi devrais-je utiliser new au lieu de old malloc () digne de confiance?

FAQ: new / delete appeler le constructeur / destructeur; nouveau est de type sûr, malloc ne l'est pas; new peut être remplacé par une classe.

FQA: Les vertus de new mentionnées par la FAQ ne sont pas des vertus, car les constructeurs, les destructeurs et la surcharge des opérateurs sont des ordures (voyez ce qui se passe lorsque vous n'avez pas de collecte des ordures?), Et le problème de sécurité du type est vraiment minuscule ici (normalement vous avez pour convertir le void * renvoyé par malloc au type de pointeur droit pour l'affecter à une variable de pointeur typée, ce qui peut être ennuyeux, mais loin d'être "dangereux").

Oh, et l'utilisation d'un vieux malloc digne de confiance permet d'utiliser le réallocation tout aussi fiable et ancien. Dommage que nous n'ayons pas un nouvel opérateur brillant à renouveler ou quelque chose.

Pourtant, nouveau n'est pas assez mauvais pour justifier un écart par rapport au style commun utilisé dans un langage, même lorsque le langage est C ++. En particulier, les classes avec des constructeurs non triviaux se comporteront de manière fatale si vous mallociez simplement les objets. Alors pourquoi ne pas utiliser new dans tout le code? Les gens surchargent rarement l'opérateur nouveau, donc cela ne vous gênera probablement pas trop. Et s'ils surchargent de nouveaux, vous pouvez toujours leur demander d'arrêter.

Désolé, je n'ai pas pu résister. :)

Matthias Benkard
la source
7
C'est une émeute ! Merci.
dmckee --- chaton ex-modérateur
8
Je ne peux pas prendre ce commentaire au sérieux car il projette clairement le parti pris de l'auteur contre C ++. C ++ est un langage utilisé pour créer des logiciels axés sur les performances, et un garbage collector ne peut que nuire à son objectif. Je suis en désaccord avec votre réponse entière!
Miguel
1
@Miguel Vous avez raté la blague.
Dan Bechard
50

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:

void *p = operator new(size);
   ...
operator delete(p);
Ferruccio
la source
3
intéressant, j'ai toujours juste alloué un tableau de caractères non signés lorsque j'ai besoin d'un tampon de données brutes comme celui-ci.
Greg Rogers
Attention la sémantique doit être comme ceci: p_var = new type (initializer); Pas de taille.
Brian R. Bondy,
11
Pas si vous appelez directement l'opérateur new, alors il faut le nombre d'octets à allouer comme paramètre.
Ferruccio
1
Hrm pas sûr, je n'ai jamais entendu parler de cette syntaxe.
Brian R. Bondy,
9
L'opposé de operator newest operator delete. Ce n'est pas une action bien définie d'appeler deleteune expression de type void*.
CB Bailey
33

Utilisez mallocet 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 newdelete[]

dmckee --- chaton ex-modérateur
la source
10
Notez également qu'une bibliothèque C bien écrite masquera malloc et la libérera en interne, c'est ainsi que le programmeur C devrait fonctionner.
Dacav
@dmckee avez-vous un exemple de C ++ utilisant des bibliothèques c-centric par malloc et gratuit?
milesma
1
@Dacav: Si une fonction C accepte un pointeur sur un objet qu'elle devra continuer à utiliser après le retour de la fonction, et que l'appelant n'aura aucun moyen de savoir quand l'objet est toujours nécessaire, ce serait parfaitement raisonnable pour la fonction pour spécifier que le pointeur doit avoir été créé avec malloc. De même, si une fonction comme a strdupbesoin de créer un objet et de le renvoyer à un appelant, il est parfaitement raisonnable de spécifier que l'appelant doit appeler freel'objet lorsqu'il n'est plus nécessaire. Comment de telles fonctions pourraient-elles éviter d'exposer leur utilisation de malloc / free à l'appelant?
supercat
@supercat, il y a quelque chose de fondamentalement erroné à ce qu'une fonction C accepte un pointeur sur des objets, car C ne connaît pas du tout les objets. En général, je pense que la meilleure approche consiste à avoir des wrappers sémantiques autour de l'allocation / désallocation également en C. Cela peut être toujours acceptable, mais moins flexible, si une bibliothèque C demande à l'appelant de pré-allouer et / ou désallouer la mémoire. Si une fonction C fait cela et revendique la propriété de la mémoire allouée, vous devez implicitement l'allouer avec malloc.
Dacav du
@supercat Un exemple de paquet quotidien que je suis sûr que tout le monde a utilisé est libgmp. Si vous avez déjà utilisé un cryptage open source ou un logiciel basé sur un tel cryptage (ce qui est très probable), vous avez probablement utilisé une bibliothèque arithmétique de précision arbitraire qui doit augmenter et réduire ses propres données internes. Cela se fait en utilisant une fonction d'initialisation ... et ensuite vous devez vous demander, comment utilisez-vous le code C qui est libgmp, en C ++, sans le recompiler en C ++? Maintenant avec cela (l'éditeur de liens) à l'esprit, pensez-y ... pourquoi une personne sensée aurait-elle jamais mis mallocen C ++?
autiste
31

new vs malloc ()

1) newest un opérateur , tandis que malloc()est une fonction .

2) newappelle les constructeurs , mais malloc()pas.

3) newrenvoie le type de données exact , tandis que malloc()renvoie void * .

4) newne renvoie jamais un NULL (lancera en cas d'échec) tandis que malloc()retourne NULL

5) Réaffectation de mémoire non traitée par newtout malloc()bidon

Yogeesh HT
la source
6
Salut, Pour le point 4), new peut être chargé de retourner NULL en cas d'échec. char* ptr = new (std::nothrow) char [323232];
Singh
1
6) new crée à partir des arguments du constructeur, tandis que malloc utilise size.
Evan Moran
il y a aussi une newfonction
Ma Ming
Si vous étiez si incliné en C à réallouer , j'espère que vous utiliseriez reallocplutôt que malloc, 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ôt std::vectorque realloc... ça ou un fichier.
autiste
19

Pour répondre à votre question, vous devez connaître la différence entre mallocetnew . La différence est simple:

malloc alloue de la mémoire , tandis que new 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 freeet deleteest tout à fait la même. La différence est que vous deleteappellerez le destructeur de votre objet en plus de libérer de la mémoire.

Le physicien quantique
la source
13

Il y a une grande différence entre mallocet new.mallocalloue 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.

newalloue 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:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

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 placementnew ).

Si, en revanche, vous faites:

non_pod_type* p = new non_pod_type();

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:

pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;

Ce morceau de code imprimerait une valeur non spécifiée, car les objets POD créés par mallocne sont pas initialisés.

Avec new, vous pouvez spécifier un constructeur à appeler et ainsi obtenir une valeur bien définie.

pod_type* p = new pod_type();
std::cout << p->foo; // prints 0

Si vous le voulez vraiment, vous pouvez utiliser use newpour 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, mallocretourne un pointeur nul, tout en newlanç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 newet non malloc. Mais même dans ce cas, vous ne devez pas utiliser new"en plein air", car il acquiert les ressources que vous devez libérer plus tard. Lorsque vous utilisez, newvous devez transmettre immédiatement son résultat à une classe de gestion des ressources:

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak
R. Martinho Fernandes
la source
7

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:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

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_ptra é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:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

C ++ 17 ajoute également std::optionalce qui peut vous empêcher d'exiger des allocations de mémoire

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

Dès que «instance» sort de la portée, la mémoire est nettoyée. Le transfert de propriété est également simple:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

Alors, quand avez-vous encore besoin new? Presque jamais à partir de C ++ 11. La plupart de ce que vous utilisez std::make_uniquejusqu'à ce que vous atteigniez un point où vous atteignez une API qui transfère la propriété via des pointeurs bruts.

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

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é:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

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.

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

Même si ce qui précède est valide, cela peut également être fait via un nouvel opérateur. std::vectoren 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:

  • Vous écrivez une bibliothèque standard avec des structures de données avancées où malloc est approprié
  • Vous devez allouer de grandes quantités de mémoire (dans la copie de mémoire d'un fichier de 10 Go?)
  • Vous disposez d'un outillage vous empêchant d'utiliser certaines constructions
  • Vous devez enregistrer un type incomplet
JVApen
la source
6

Il y a quelques choses qui newne le mallocfont pas:

  1. new construit l'objet en appelant le constructeur de cet objet
  2. new ne nécessite pas de transtypage de la mémoire allouée.
  3. Il ne nécessite pas une quantité de mémoire à allouer, il nécessite plutôt un certain nombre d'objets à construire.

Donc, si vous utilisez malloc, vous devez faire les choses ci-dessus explicitement, ce qui n'est pas toujours pratique. De plus, newpeut être surchargé mais mallocne peut pas l'être.

herohuyongtao
la source
5

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 ++.

PSkocik
la source
3

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.

Fred Larson
la source
3

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.

user3488100
la source
2

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

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

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.

lama12345
la source
1

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.

Peiti Li
la source
4
new n'initialise généralement pas la mémoire, bien qu'il existe des moyens d'y parvenir: voir stackoverflow.com/questions/2204176/… pour une discussion à ce sujet.
wjl
0

Dans le scénario suivant, nous ne pouvons pas utiliser new car il appelle constructeur.

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};
Barry
la source
0

Les opérateurs newet deletepeuvent fonctionner sur les classes et les structures, tandis que mallocet freene fonctionnent qu'avec les blocs de mémoire qui doivent être convertis.

L'utilisation vous new/deleteaidera à améliorer votre code car vous n'aurez pas besoin de convertir la mémoire allouée en la structure de données requise.

selwyn
la source
0

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 ++).

Florentino Tuason
la source
-4

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 ()

Hitesh Ahuja
la source
2
Vous pouvez (mais presque toujours ne devriez pas) utiliser mallocen C ++.
interjay
1
Vous avez également manqué le point principal que vous devriez viser à éviter l'allocation dynamique de mémoire, sauf si vous le faites via des pointeurs intelligents. Vous vous
préparez