2009-09-01 18 views
2

Comment C++ s'assure-t-il que les destructeurs sont appelés pour les objets affectés à la pile? Qu'advient-il de la fonction destructor (ou un pointeur vers elle) quand je cède la mémoire dynamique comme suit:Quel est le mécanisme par lequel les destructeurs sont appelés pour les objets affectés par la pile?

class MyClass { 
public: 

    ~MyClass() 
    { 
    std::cout<<"Destructor called."<<std::endl; 
    } 

    MyClass() 
    { 
    std::cout<<"Constructor called."<<std::endl; 
    } 

}; 

.................................................................... 

//Limit scope for example 
{ 
    MyClass instance; 
} 

Le constructeur et destructor sont tous deux appelés. Que se passe t-il ici?

+0

instance est le nom de l'objet. instance() est simplement un appel à l'argument no ctor de la classe.Les parens sont inutiles dans ce cas, mais ce n'est certainement pas un appel à une méthode appelée instance(). – dicroce

+5

Je ne vois aucune allocation de mémoire dynamique. –

Répondre

7

Le compilateur insère un appel au destructeur pour l'objet à une position appropriée.

1

Le constructeur est appelé car vous créez un objet. Le destructeur est appelé parce que vous nettoyez cet objet. Rappelez-vous qu'en C++, les objets déclarés sur la pile sont automatiquement nettoyés lorsque leur portée contenante disparaît.

3

Le constructeur est appelé dès que la variable est créée. Comme pour le destructeur, le compilateur émet du code à la fin de la portée pour appeler le destructeur. Pour avoir une idée de cela, essayez d'utiliser un 'goto', ou une construction switch/case pour quitter prématurément la portée, et regarder le compilateur se plaindre.

+1

"Le constructeur est appelé dès que la variable est créée." Eh bien, la création d'objet se produit lorsque le constructeur est appelé, donc ce n'est pas étonnant. La mémoire de la variable, OTOH, peut être fournie plus tôt. – sbi

+1

Vous pouvez quitter la portée avec goto, pour autant que je sache, et le compilateur saura toujours que l'objet est hors de portée. Ce que vous n'êtes pas autorisé à faire est de passer au-dessus des déclarations d'objets (construction) avec goto/switch. – UncleBens

+0

@UncleBens: Faites ce "définitions d'objet", mais sinon vous avez raison. (J'ai lu trop vite et je n'avais même pas vu cette erreur dans la réponse de Managu.) – sbi

3

Oui, le constructeur et le destructeur sont appelés. Et encore plus important:

{ 
MyClass instance; 
throw "exception"; 
} 

Dans cet exemple, le destructeur est également appelé. C'est pourquoi je préfère toujours allouer mes objets sur la pile (ou au moins envelopper les allocations dynamiques avec un gardien attribué par la pile).

4

Vous ne me demande pourquoi ce

{ 
    int i; 
} 

crée et détruit automatiquement i, vous? C++ fait beaucoup pour vous permettre de créer des types qui se comportent comme des types intégrés. Et tout comme avec types intégrés, en C++ (autres que, disons, Java ou C#), ce

{ 
    MyClass instance; 
} 

ne définit pas seulement une référence qui pourrait être lié à null ou d'un objet réel. crée un objet réel.

La création d'objet se fait en deux étapes: d'abord (lors de l'entrée dans la portée) la mémoire brute est fournie. Ensuite (lorsque la définition de l'objet est rencontrée) le constructeur est appelé. Pour les types intégrés, aucun constructeur n'est appelé. Si vous n'initialisez pas une variable intégrée, elle a une valeur aléatoire. (En fait, il s'agit du modèle de bits fourni à l'étape 1). La suppression d'un objet s'effectue également en deux étapes: d'abord, le destructeur est appelé (et non pour les fonctions intégrées), puis la mémoire est renvoyée. le système d'exécution.

(Notez que la fourniture et la suppression de la mémoire pour les variables de la pile est généralement aussi pas cher que incementing/décrémenter un registre.)

0

Eh bien, il n'a pas appelé la destructor juste après le constructeur.
Il l'appelle lorsqu'il est sur le point de terminer le programme.

int main() { 
    MyClass obj; 
    cout<<"testing....1"<<endl; 
    cout<<"testing....2"<<endl; 
    return 0; 
} 

ans:

Constructor called. 
testing....1 
testing....2 
Destructor called. 
+1

Il n'appelle pas le destructeur lorsque le programme est sur le point de se terminer. Le destructeur est appelé lorsque l'objet de pile est hors de portée. Parce que vous faites cela en main, ces deux coïncident. –