2010-06-25 4 views
3

J'essaie de comprendre ce qui se passe en C++. S'il vous plaît considérer les points suivants:Affectation d'une valeur passée en référence à une variable membre (en C++)

class C 
{ 
    int i_; 
public: 
    C() { i_ = 0;} 
    C(int i) { i_ = i; } 
    C(const C &c) { 
     i_ = c.i_; 
     cout << "C is being copied: " << i_ << endl; 
    } 
    int getI() { return i_; } 
    ~C() {cout << "dstr: " << i_ << endl;} 
}; 

class D 
{ 
    C c_; 
public: 
    void setC(C &c) { c_ = c; } 
    int getC_I() { return c_.getI(); } 
}; 

void Test(D &d) 
{ 
    C c(1); 
    d.setC(c); 
    //here c is going out of scope, surely it will be destroyed now? 
} 

int main() 
{ 
    D d; 
    Test(d); //this sets value of c_ to the local variable in Test. 
      //Surely this will be invalid when Test returns? 
    int ii = d.getC_I(); 
    cout << ii << endl; 
} 

L'exécution de cette sortie du programme:

DSTR: 1
DSTR: 1

Apparemment, le premier appel destructor se produit dans le test, et l'autre lorsque le programme se termine et d est détruit. Donc, ma question est: Où a été copié? Y a-t-il un défaut de raisonnement? Et point général que j'essaie de poser: est-il sûr d'avoir une fonction membre qui prend une référence à un objet et le stocke ensuite dans une variable membre?

Merci beaucoup pour votre aide.

Répondre

2

Votre code est correct à l'heure actuelle. D::c_ est de type C plutôt que C &. Votre SetC prend une référence à un C et affecte la valeur référencée par cette référence à C::c_, ce que vous avez est un objet C entièrement séparé qui a la même valeur. Depuis que vous avez créé d avec la durée de stockage automatique dans main, il et c_ qui en fait partie restent valides jusqu'à ce que vous sortiez de main.

2

Où a été copié?

Lorsque vous faites c_ = c;Where was c copied?, vous appelez operator= sur c_ qui copie le contenu de c à c_.

Si c_ étaient également une référence, rien ne serait copié, et le programme provoquerait une erreur comme vous l'attendez.

2

C se copie ici:

void setC(C &c) { c_ = c; } 

Si vous souhaitez stocker une référence alors votre variable membre c_ doit également être une référence. Si vous stockez une référence, vous devrez faire attention à la durée de vie de la variable que vous transmettez.

+0

@Charles la norme dit "Un objet de classe peut être copié de deux manières, par initialisation [...], et par assignation (5.17) .. Conceptuellement, ces deux opérations sont implémentées par un constructeur de copie (12.1) et copient opérateur d'affectation (13.5.3). " –

+0

@litb: Juste point, je retire mon commentaire original et ma réponse. –

Questions connexes