123 votes

Création d'une instance de la classe

Quelle est la différence entre les lignes 1, 2, 3 et 4 ?

Quand dois-je les utiliser ?

Pourquoi la ligne 3 imprime le constructor Foo et la ligne 7 renvoie une erreur alors que la ligne 8 n'en renvoie pas ?

#include <iostream>     
using namespace std;

class Foo
 {
   public:
   Foo ( )
   {
      cout << "constructor Foo\n";
   }               
};

class Bar
 {
   public:
   Bar ( Foo )
   {
      cout << "constructor Bar\n";
   }
};

int main()
{
   /* 1 */ Foo* foo1 = new Foo ();
   /* 2 */ Foo* foo2 = new Foo;
   /* 3 */ Foo foo3;
   /* 4 */ Foo foo4 = Foo::Foo();

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );
   /* 6 */ Bar* bar2 = new Bar ( *new Foo );
   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );
   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );

   return 1;
}

150voto

Luchian Grigore Points 136646
   /* 1 */ Foo* foo1 = new Foo ();

Crée un objet de type Foo dans la mémoire dynamique. foo1 pointe vers lui. Normalement, on n'utilise pas de pointeur brut en C++, mais plutôt un pointeur intelligent. Si Foo était un type POD, cela effectuerait une initialisation de la valeur (cela ne s'applique pas ici).

   /* 2 */ Foo* foo2 = new Foo;

Identique à l'ancienne, car Foo n'est pas un type de POD.

   /* 3 */ Foo foo3;

Crée un Foo objet appelé foo3 en stockage automatique.

   /* 4 */ Foo foo4 = Foo::Foo();

Utilise l'initialisation par copie pour créer un fichier Foo objet appelé foo4 en stockage automatique.

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );

Utilisations Bar Le constructeur de conversion de l'utilisateur crée un objet de type Bar en stockage dynamique. bar1 est un pointeur sur celui-ci.

   /* 6 */ Bar* bar2 = new Bar ( *new Foo );

Comme avant.

   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );

C'est juste une syntaxe invalide. Vous ne pouvez pas déclarer une variable à cet endroit.

   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );

Travaillerait et fonctionnerait selon le même principe que 5 et 6 si bar3 n'a pas été déclaré en 7.

5 & 6 contiennent des fuites de mémoire.

Syntaxe comme new Bar ( Foo::Foo() ); n'est pas habituel. C'est habituellement new Bar ( (Foo()) ); - les parenthèses supplémentaires représentent l'analyse la plus complexe. (corrigé)

25voto

Mike Seymour Points 130519
  1. Alloue de la mémoire dynamique à partir du magasin libre, et crée un objet dans cette mémoire en utilisant son constructeur par défaut. Vous ne le supprimez jamais, la mémoire est donc perdue.
  2. Fait exactement la même chose que 1 ; dans le cas de types définis par l'utilisateur, les parenthèses sont facultatives.
  3. Alloue de la mémoire automatique, et crée un objet dans cette mémoire en utilisant son constructeur par défaut. La mémoire est libérée automatiquement lorsque l'objet sort de sa portée.
  4. Similaire à 3. Notionnellement, l'objet nommé foo4 est initialisé par défaut en construisant, copiant et détruisant un objet temporaire ; habituellement, ceci est élidé donnant le même résultat que 3.
  5. Alloue un objet dynamique, puis en initialise un second en copiant le premier. Les deux objets sont perdus, et il n'y a aucun moyen de supprimer le premier puisque vous ne conservez pas de pointeur sur lui.
  6. Fait exactement la même chose que 5.
  7. Ne se compile pas. Foo foo5 est une déclaration, pas une expression ; les arguments des fonctions (et des constructeurs) doivent être des expressions.
  8. Crée un objet temporaire, et initialise un objet dynamique en le copiant. Seul l'objet dynamique est fui ; le temporaire est détruit automatiquement à la fin de l'expression complète. Notez que vous pouvez créer le temporaire avec seulement Foo() plutôt que l'équivalent Foo::Foo() (ou bien Foo::Foo::Foo::Foo::Foo() )

Quand dois-je les utiliser ?

  1. Ne le faites pas, sauf si vous aimez les décorations inutiles sur votre code.
  2. Lorsque vous voulez créer un objet qui dépasse la portée actuelle. N'oubliez pas de le supprimer lorsque vous n'en avez plus besoin et apprenez à utiliser la fonction pointeurs intelligents pour contrôler la durée de vie de manière plus pratique.
  3. Lorsque vous voulez un objet qui n'existe que dans la portée actuelle.
  4. Ne le faites pas, à moins que vous ne pensiez que 3 soit ennuyeux et que vous vouliez ajouter une décoration inutile.
  5. Ne le faites pas, car cela fait perdre de la mémoire sans possibilité de récupération.
  6. Ne le faites pas, car cela fait perdre de la mémoire sans possibilité de récupération.
  7. Ne le faites pas, car il ne compilera pas.
  8. Lorsque vous voulez créer une Bar à partir d'un Foo .

5voto

Coding Mash Points 3076

Les lignes 1,2,3,4 appelleront le constructeur par défaut. Elles sont différentes dans leur essence car 1,2 sont des objets créés dynamiquement et 3,4 sont des objets créés statiquement.

Dans la ligne 7, vous créez un objet dans l'appel de l'argument. C'est donc une erreur.

Et les lignes 5 et 6 sont une invitation à la fuite de mémoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X