2017-09-29 4 views
-2
#include <iostream> 

using namespace std; 

class MyClass { 
    int x; 
    public: 
    MyClass (int val) : x(val) { 
     cout << "constructed :" << this << endl; 
    } 
    int& get() { 
     cout << "x is : " << x << endl ; 
     return x; 
    } 
}; 

int main() { 
    MyClass foo = {10}; 
    foo.get() = 20; 
    foo.get(); 
    foo = 30; 
    cout << &foo << endl; 
    foo.get(); 
} 

je reçois la sortie suivante:Pourquoi cette fonction dans une classe initialise une valeur de membre avec cet appel étrange?

constructed :0x7fffc44ef920 
x is : 10 
x is : 20 
constructed :0x7fffc44ef924 
0x7fffc44ef920 
x is : 30 

Pourquoi cette foo.get() = 20 un moyen légitime de changer la valeur de « x » dans l'objet foo?

Aussi pourquoi est ce foo = 30 la construction d'un nouvel objet à l'adresse 0x7fffc44ef924? Quel est ce type d'objet?

Pourquoi aussi: cout << &foo << endl; imprime l'adresse de l'objet original MyClass fooo instancié au début de la fonction principale (à l'adresse 0x7fffc44ef920)?

Comment référencez-vous le 'nouveau' foo à l'adresse 0x7fffc44ef924?

+0

essayez avec 'explicit' devant le constructeur à un paramètre - cela devrait vous apprendre beaucoup de choses. –

+8

Sons comme vous pourriez utiliser un [bon livre C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – NathanOliver

+0

une question par question s'il vous plaît – user463035818

Répondre

1

Pourquoi foo.get() = 20 est-il un moyen légitime de changer la valeur de 'x' dans l'objet foo?

Parce que vous retournez une référence à x et comment se comportent les références. En fait, la seule raison que je connaisse pour retourner une référence d'une fonction (int &get()) est d'autoriser ce comportement. Vous pouvez le faire, par exemple, si vous implémentez l'opérateur [].

Parfois, vous voulez renvoyer une référence const (const int &foo()) afin d'éviter une copie de la valeur, mais vous ne le feriez qu'avec une classe ou une structure.

Aussi pourquoi est-ce foo = 30 construire un nouvel objet à l'adresse 0x7fffc44ef924? Quel est ce type d'objet?

Parce que MyClass a un constructeur qui prend un argument int, le compilateur interprète cela comme un moyen de convertir un entier à un MyClass, qui est ce qui se passe ici. Il est équivalent à foo = MyCLass(int) Si vous ne voulez pas ce comportement, vous pouvez déclarer MyClass (int) comme explicite:

explicit MyClass(int val) {... 

également pourquoi cette foo = 30 un nouvel objet à l'adresse 0x7fffc44ef924? Quel est ce type d'objet?

aussi pourquoi cette: Cout < < & foo < < endl; imprime l'adresse de l'objet original MyClass instancié au début de la fonction principale (à l'adresse 0x7fffc44ef920)?

D'abord, la classe MyClass implicite (30) que j'ai décrite ci-dessus est utilisée pour construire un nouvel objet MyClass. L'adresse de cet objet se trouve avoir l'adresse 0x7fffc44ef924 puis le nouvel objet est copié dans l'ancien objet, à 0x7fffc44ef920. Probablement, si vous avez activé l'optimisation, vous ne verrez qu'une seule adresse, car le compilateur verrait que créer un nouvel objet et le copier est un gaspillage de cycles CPU.

Comment référencer le 'nouveau' foo à l'adresse 0x7fffc44ef924?

Vous ne pouvez pas, cet objet a été créé et détruit dans une ligne de code. Une fois qu'il a été copié sur l'objet original comme je l'ai décrit ci-dessus, il a été supprimé.

0

Changer votre constructeur à un un explicite, en ajoutant le mot-clé explicit avant votre constructeur, comme ceci:

explicit MyClass (int val) : x(val) { 
    cout << "constructed :" << this << endl; 
} 

Ensuite, vous obtiendrez des messages très instructifs du compilateur:

prog.cc: In function 'int main()': 
prog.cc:18:22: error: converting to 'MyClass' from initializer list would use explicit constructor 'MyClass::MyClass(int)' 
    MyClass foo = {10}; 
        ^
prog.cc:21:11: error: no match for 'operator=' (operand types are 'MyClass' and 'int') 
    foo = 30; 
      ^~ 
prog.cc:5:7: note: candidate: 'constexpr MyClass& MyClass::operator=(const MyClass&)' 
class MyClass { 
     ^~~~~~~ 
prog.cc:5:7: note: no known conversion for argument 1 from 'int' to 'const MyClass&' 
prog.cc:5:7: note: candidate: 'constexpr MyClass& MyClass::operator=(MyClass&&)' 
prog.cc:5:7: note: no known conversion for argument 1 from 'int' to 'MyClass&&' 

Lisez-les et comprenez-le. Si elles n'ont pas de sens, alors vous avez vraiment besoin d'étudier C++ plus, par exemple. un book.