2010-06-06 13 views
1

je le code suivantdestructor et appeler constructeur de copie .. (pourquoi est-elle appelée à ces moments)

#include <iostream> 
using namespace std; 

class Object { 

public: 
    Object(int id){ 
    cout << "Construct(" << id << ")" << endl; 
    m_id = id;  
    } 

    Object(const Object& obj){ 
     cout << "Copy-construct(" << obj.m_id << ")" << endl; 
     m_id = obj.m_id; 
    } 

    Object& operator=(const Object& obj){ 
     cout << m_id << " = " << obj.m_id << endl; 
     m_id = obj.m_id; 
     return *this; 
    } 

    ~Object(){ 
     cout << "Destruct(" << m_id << ")" << endl; 
    } 
private: 
    int m_id; 

}; 

Object func(Object var) { return var; } 

int main(){ 
    Object v1(1); 
    cout << "(a)" << endl; 
    Object v2(2); 
    v2 = v1; 
    cout << "(b)" << endl; 
    Object v4 = v1; 
    Object *pv5; 
    pv5 = &v1; 
    pv5 = new Object(5); 
    cout << "(c)" << endl; 
    func(v1); 
    cout << "(d)" << endl; 
    delete pv5; 
} 

qui sort

Construct(1) 
(a) 
Construct(2) 
2 = 1 
(b) 
Copy-construct(1) 
Construct(5) 
(c) 
Copy-construct(1) 
Copy-construct(1) 
Destruct(1) 
Destruct(1) 
(d) 
Destruct(5) 
Destruct(1) 
Destruct(1) 
Destruct(1) 

J'ai quelques problèmes avec cela, d'une part pourquoi Object v4 = v1; appelle le constructeur de copie et produit Copy-construct(1) après l'impression de (b).

également après l'impression de (c) le constructeur de copie est à nouveau appelé deux fois ?, je ne suis pas certain de la façon dont cette fonction fonctionne pour produire cette Object func(Object var) { return var; }

et juste après que Destruct(1) est appelé deux fois avant de (d) est imprimé.

désolé pour la longue question, je suis confus avec ce qui précède.

Répondre

3
Object v1(1); 
// Construct(1) 

Appel de constructeur régulier pour une variable de pile automatique (détruite à la fin de la fonction).

cout << "(a)" << endl; 
// (a) 

Object v2(2); 
// Construct(2) 

Un autre appel de constructeur.

v2 = v1; 
// 2 = 1 

L'opérateur d'affectation est appelé car v2 a déjà été créé (nous avons appelé le constructeur pour elle) et maintenant nous assignons un objet existant à un autre. Le constructeur de copie est appelé ici parce que l'objet v4 n'est toujours pas créé, donc nous le créons comme une copie de v1. L'affectation est prise ici pour dire la même chose que si vous avez fait Object v4(v1)

Object *pv5; 
pv5 = &v1; 
pv5 = new Object(5); 
// Construct(5) 

Appelez le constructeur pour un objet tas (détruit explicitement delete).

cout << "(c)" << endl; 
// (c) 

func(v1); 
// Copy-construct(1) <br /> 
// Copy-construct(1) <br /> 
// Destruct(1) <br /> 
// Destruct(1) <br /> 

Le constructeur de copie est d'abord appelé pour copier v1 dans le paramètre var. Il est appelé à nouveau pour créer une copie de var comme valeur de retour à l'appelant. var est détruit car il est retiré de la pile en quittant la fonction. La valeur de retour est détruite après l'expression func (v1).

cout << "(d)" << endl; 
// (d) 

delete pv5; 
// Destruct(5) 

L'objet pointé par pv5 est détruit manuellement.

} // end of main 
// Destruct(1) <br /> 
// Destruct(1) <br /> 
// Destruct(1) <br /> 

les variables automatiques v1, v2, v4 (tous avoir copié l'id de v1 soit de l'affectation ou de copie construction) sont extraits de la pile et le destructeur est appelé pour chaque.

1

En ce qui concerne la première question, Object v4 = v1; est le sucre syntaxique pour Object v4(v1);, qui appelle plus apparemment le constructeur de copie.

La seconde est un peu plus compliquée. Lors du passage de variables par valeur à des fonctions, elles doivent être copiées - donc un appel au constructeur de copie. Une copie de l'objet doit également être placée sur la pile dans un emplacement où l'appelant peut y accéder car la copie transmise à la fonction cesse d'exister lorsque la fonction revient. Une fois ces deux copies effectuées, le paramètre est détruit lorsqu'il est retiré de la pile et la valeur de retour est détruite car sa valeur n'est pas utilisée. Ils ont le même ID parce qu'ils sont des copies de v1.

+0

ahk merci beaucoup. aussi une question de plus, les 3 dernières sorties de 'Destruct (1)' sont dues à 'Object v1 (1) ;, v2 = v1, Object v4 = v1;' correct? et 'Destruct (5)' est venu juste avant comme il a été supprimé manuellement? – silent

2

J'ai quelques problèmes avec cela, d'abord pourquoi Object v4 = v1; appelez le constructeur de copie et de produire Copier-construire (1) après l'impression de (b).

Malgré le signe =, vous appelez le constructeur de copie ici. Rappelez-vous, vous n'avez aucun constructeur par défaut. Vous construisez un nouveau Object et l'initialisez avec la valeur v1. Avez-vous été à faire:

cout << "(b)" << endl; 
Object v4(0); 
v4 = v1; 

... vous verriez ...

(b) 
Construct(0) 
0 = 1 

... que je pense que vous attendiez.

également après l'impression de (c) la copie constructeur est à nouveau appelé deux fois ?, je ne suis pas certain de la façon dont cette fonction fonctionne pour produire cet objet func (Object var) {return var; }

Ici vous passez var en valeur (plutôt que par référence [&]), ce qui signifie qu'une copie de l'objet est créé (un appel au constructeur de copie). Ensuite, vous renvoyez un autre objet (encore une fois, plutôt qu'une référence) afin qu'une autre copie doit être effectuée (un deuxième appel au constructeur de copie).

et juste après cela Destruct (1) obtient appelé deux fois avant que (d) soit imprimé.

Objets que vous venez de créer avec les constructeurs de copie? Ils sont juste sortis de la portée et leurs destructeurs ont été appelés.

Lorsque vous deletev5 son destructeur est appelé.

Ensuite, vous atteignez la fin de votre fonction main et les trois instances Object vous avez créé sur la pile (v1, v2, v4) atteignent la fin de leur vie et sont détruits lorsque la pile est dévidé.

Vous avez probablement déjà remarqué que vous avez exactement autant d'appels de destructeurs que vous avez d'appels de constructeurs!

+0

pourriez-vous expliquer les 4 derniers appels de destructeur aussi ?. – silent

+1

J'ai mis à jour ma réponse pour les expliquer. – Johnsyweb