web-dev-qa-db-fra.com

Initialisation d'un objet avec et sans nouvel opérateur

Si j'ai une classe Rectangle

class Rectangle{

private:
    double width;
    double height;


public:
void    Set(double w , double l){
    width   = w;
    height  = l;
}
};

et je décleare un objet tel:

Rectangle *Obj;

puis essayez d'initialiser ses propriétés:

Obj->Set(3,5);

le compilateur affiche au moment de l'exécution: The variable 'Obj' is being used without being initialized.

Le problème peut être résolu par:

Rectangle *Obj=new Rectangle;

Je demanderais la raison! Et pourquoi le compilateur n'affiche aucune erreur au moment de la compilation?

22
Aan
Rectangle *Obj;

définit juste un pointeur vers un objet de classe Rectangle. La définition d'un pointeur ne réserve aucune mémoire pour l'objet lui-même, juste pour le pointeur . Ainsi, si vous accédez au pointeur, vous vous retrouverez probablement à une adresse en mémoire qui n'appartient même pas à votre processus. Cependant, le compilateur ne peut pas savoir que vous n'avez pas initialisé le pointeur (le mot clé ici est aliasing) et ne peut donc pas générer de message d'erreur.

La solution utilise soit new comme vous l'avez suggéré, soit déclare une instance de Rectangle comme ceci:

Rectangle Obj;

qui appellera un constructeur par défaut. Vous pouvez ensuite définir vos membres en utilisant

Obj.Set(3, 5);
24
arne

et je décleare un objet tel:

Rectangle *Obj;

Mal, cela déclare un pointeur, pas un objet. Les pointeurs doivent être initialisés en utilisant new ou en leur affectant l'adresse d'un objet existant.

8
Björn Pollex

Mmm un peu de confusion là-bas:

le compilateur affiche au moment de l'exécution: la variable 'Obj' est utilisée sans être initialisée

C'est ce que vous appelleriez temps de compilation. Simplement redresser le jargon.

De plus, le moyen le plus simple serait de

Rectangle Obj;
Obj.Set(3,5);

ce qui est suffisant pour la plupart des scénarios, à l'exception des allocations dynamiques ou des conteneurs polymorphes:

std::vector<Shape*> v;
v.Push_back(new Rectange());
v.back()->Set(3,5);

v.Push_back(new Circle());
v.back()->Set(3,5);

//

Bien que chaque fois que vous utilisez new, vous devez également vous souvenir de delete. Cela peut être tout à fait un cauchemar (à la lumière d'exceptions aussi). Je suggère:

std::vector<std::shared_ptr<Shape*> > v;
v.Push_back(std::make_shared<Rectange>());
v.back()->Set(3,5);

v.Push_back(std::make_shared<Circle>());
v.back()->Set(3,5);
4
sehe

pointer without new déclare quelque chose sans mémoire .. SO u doit utiliser new avec pointer. Cependant Rectangle rect; allouera par défaut la mémoire.

pour vérifier cela, faites un constructeur dans la classe Rectangle comme,

void Rectangle
{
  cout<<"Rectangle Constructor";
}

puis, en principal

Rectangle *rect; -->>O/P  -- "Nothing"
Rectangle rect2; -->>O/P  -- Rectangle Constructor
rect=new Rectangle; -->>O/P  -- Rectangle Constructor
3
Subhranshu

Avec Rectangle *Obj;, vous déclarez un pointeur sur un rectangle, mais vous n'avez pas dit à Obj vers quel rectangle il doit pointer. Vous pouvez définir ou instancier Obj ultérieurement sur un Rectangle existant ou uniquement si vous en avez besoin.

C++ vise à vous donner un contrôle précis sur votre mémoire et vos performances. En fait, c'est pourquoi il est utilisé dans certains environnements embarqués! L'instanciation automatique de Obj pose plusieurs "problèmes"

  • Quand libérons-nous Obj?
  • Qui libère Obj?
  • Qu'en est-il des implications en termes de performances de la création d'un Rectangle sur le tas?
  • Est-ce un environnement dans lequel nous avons suffisamment de ressources (mémoire, CPU, etc.) pour même créer le rectangle, surtout s'il est grand.
  • Passez-vous quelque part l'adresse de Obj, puis instanciez-la au moment de l'exécution à l'aide d'une méthode complexe que nous ne pouvons pas analyser statiquement?

Ce que vous faites n'est pas une erreur de syntaxe, c'est ce sur quoi les compilateurs jettent des erreurs - des erreurs lors de la compilation. Un analyseur (l'un est intégré à Visual Studio 2010 Professional) peut vous avertir que vous utilisez une variable non initialisée, bien que cela soit facultatif et que vous deviez l'activer.

3
foxy

pourquoi le compilateur n'affiche aucune erreur au moment de la compilation?

Parce que c'est syntaxiquement correct. Cependant, de telles instructions conduiront à comportement indéfini, les compilateurs intelligents émettront toujours un avertissement.

Dans g ++, vous pouvez transformer ce type d'avertissement du compilateur en erreurs.

2
iammilind