2017-09-04 1 views
-2

Considérez le code suivant. Il définit une classe Test avec une variable membre int &m et une fonction membre Print() qui imprime la valeur et l'adresse de m.Comprendre le comportement de cet extrait de code: valeur imprimée et adresse du différentiel int référencé

#include <iostream> 

using namespace std; 

class Test 
{ 
    public: 
     int &m; 
     Test(int n); 
     void Print(); 
}; 

Test::Test(int n) : m(n) {}; 
void Test::Print() {cout << m << "\t" << &m << endl; }; 

int main() 
{ 
    int a = 2; 
    Test test1(a); 
    Test test2(a); 
    test1.Print(); 
    test2.Print(); 
    return 0; 
} 

Il est sortie est

Printing.... 2  0x7ffd2744cf0c                                    
Printing.... 2  0x7ffd2744cf08                                    

Si je change le constructeur Test(int n) être les suivants

Test::Test(int n) : m(n) {cout << "Constructing\t" << n << "\t" << &n << endl;}; 

Je place obtenir

Constructing 2  0x7ffc233ef15c                                    
Constructing 2  0x7ffc233ef15c                                    
Printing.... 2  0x7ffc233ef15c                                    
Printing.... 32597 0x7ffc233ef15c                                    

Pourquoi m a-t-il la valeur 32597 dans test2? Je vois que l'adresse de m est maintenant le même entre les deux Test objets test1 et test2 mais je ne suis pas sûr pourquoi changer le constructeur à la sortie de la valeur et l'adresse de celui-ci est entrée n aurait une incidence sur la valeur ou l'adresse de la variable m qui n est utilisé pour instancier.

+2

Si dans un code relativement trivial (comme le vôtre) il y a une valeur étrange, vous pouvez être sûr que c'est un comportement indéfini et pas un bug de logique quelque part. – Rakete1111

+0

@ Rakete1111 Ouais, j'ai pensé que c'était un comportement indéfini puisque 'm' dans' test2' est aléatoire quand j'exécute le code. Mais c'est littéralement le premier code C++ que j'ai écrit et je ne comprends pas pourquoi changer 'Test()' rend le comportement indéfini. Ma compréhension est que l'instruction 'cout' ajoutée à' Test() 'ne change pas' n' ou 'm'. Des pensées sur ce qui se passe? – Blackmill

+0

Vous savez, ce n'est pas défini pour une raison. Peut-être que si vous ajoutez 'int a = 9;' à la fin de votre code, votre ordinateur va exploser. Qui sait: P – Rakete1111

Répondre

4

Vous stockez une référence au paramètre n et la durée de vie n se termine lorsque le constructeur a terminé l'exécution.

Toute utilisation de m après ce point est indéfinie, car l'objet auquel elle fait référence n'existe plus.

Votre programme peut sembler faire quelque chose qui semble raisonnable, ou il peut faire quelque chose qui est juste bizarre, mais ce n'est pas un programme C++ valide.

+0

Appréciez la réponse. Pourriez-vous expliquer brièvement pourquoi 'm' semble défini dans la partie initiale du code puisqu'il produit la sortie' 2' pour les deux objets 'Test'? D'une certaine manière, l'ajout de 'cout' à' Test() 'change-t-il la durée de vie du constructeur? – Blackmill

+2

En examinant le comportement d'un programme C++, vous ne pouvez pas dire qu'il est * non * indéfini. Ce qui se passe probablement, c'est que la valeur de l'objet "mort" n'a pas encore été écrasée quand vous l'avez lu, mais c'est juste de la malchance. – molbdnilo

1

Vous transmettez n par copie.

Le constructeur crée une référence à la copie .

La copie disparaît après l'appel du constructeur.

La référence est indéfinie car la copie a disparu. Faites le paramètre dans votre constructeur int& n comme dans Test(int& n).