web-dev-qa-db-fra.com

Créer une instance de classe

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

Quand est-ce que je les utilise?

Pourquoi la ligne 3 imprime le constructor Foo et la ligne 7 renvoie une erreur et la ligne 8 ne le fait 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;
}
90
Kolyunya
   /* 1 */ Foo* foo1 = new Foo ();

Crée un objet de type Foo dans la mémoire dynamique. foo1 pointe vers elle. Normalement, vous n'utiliseriez pas de pointeurs bruts en C++, mais plutôt un pointeur intelligent. Si Foo était un type POD, cela initialiserait la valeur (cela ne s'applique pas ici).

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

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

   /* 3 */ Foo foo3;

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

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

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

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

Utilise le constructeur de conversion de Bar pour créer un objet de type Bar dans la mémoire de stockage dynamique. bar1 est un pointeur sur celui-ci.

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

Pareil qu'avant.

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

Ceci est juste la syntaxe invalide. Vous ne pouvez pas déclarer une variable ici.

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

Travaillerait et fonctionnerait selon le même principe à 5 et 6 si bar3 n'était pas déclaré dans 7.

5 & 6 contenir des fuites de mémoire.

Une syntaxe comme new Bar ( Foo::Foo() ); n'est pas habituelle. C'est généralement new Bar ( (Foo()) );extra parenthèses compte pour l'analyse la plus frustrante. (corrigée)

111
Luchian Grigore
  1. Alloue de la mémoire dynamique à partir du magasin libre et crée un objet dans cette mémoire à l'aide de 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 à l'aide de son constructeur par défaut. La mémoire est libérée automatiquement lorsque l'objet sort de la portée.
  4. Semblable à 3. Notionnellement, l'objet nommé foo4 est initialisé en construisant, copiant et détruisant par défaut un objet temporaire; généralement, ceci est élidé donnant le même résultat que 3.
  5. Alloue un objet dynamique, puis initialise une seconde en copiant le premier. Les deux objets sont fuites; et il n'y a aucun moyen de supprimer le premier car vous ne gardez pas un pointeur dessus.
  6. Fait exactement la même chose que 5.
  7. Ne compile pas. Foo foo5 est une déclaration et non une expression. Les arguments de fonction (et constructeur) doivent être des expressions.
  8. Crée un objet temporaire et initialise un objet dynamique en le copiant. Seul l'objet dynamique est divulgué; le temporaire est automatiquement détruit à 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 est-ce que je les utilise?

  1. Ne le faites pas, sauf si vous aimez les décorations inutiles sur votre code.
  2. Lorsque vous souhaitez créer un objet qui survit à la portée actuelle. N'oubliez pas de le supprimer lorsque vous avez terminé et d'apprendre à utiliser pointeurs intelligents pour contrôler la durée de vie plus facilement.
  3. Lorsque vous voulez un objet qui n'existe que dans la portée actuelle.
  4. Ne le faites pas, à moins que vous pensiez que 3 semble ennuyeux et qu’il faut ajouter une décoration inutile.
  5. Ne le faites pas, car il perd de la mémoire sans possibilité de récupération.
  6. Ne le faites pas, car il perd de la mémoire sans possibilité de récupération.
  7. Non, parce que ça ne compilera pas
  8. Lorsque vous souhaitez créer un Bar dynamique à partir d'un Foo temporaire.
18
Mike Seymour

Les lignes 1,2,3,4 appellent le constructeur par défaut. Ils sont fondamentalement différents en ce que 1,2 est un objet créé dynamiquement et 3,4, de manière statique.

Dans la ligne 7, vous créez un objet dans l'appel d'argument. Donc c'est une erreur.

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

5
Coding Mash