Salut, et bienvenue sur le forum.
1) la réponse simple : parce que c'est comme cela
La réponse longue:
Lorsque l'on transmet une donnée quelconque par valeur (donc, sans utiliser les références ou les pointeurs), il y a forcément création d'une copie de la donnée en question.
On peut facilement s'en rendre compte avec un code aussi simple que
1 2 3 4 5 6 7 8 9 10 11
| void add_two(int value){
value +=2;
std::cout<<"dans add_two, value = " << value<<"\n";
}
int main(){
int value{5};
std::cout<<"Avant add_two, value = " <<value<<"\n";
add_two(value);
std::cout<<" Apres add_two, value = "<<value<<"\n";
return 0;
} |
qui, une fois compilé et exécuté va provoquer l'affichage
1 2 3
| Avant add_two, value = 5
dans add_twoo, value = 7
Apres add_two, value = 5 |
Ce code nous permet de nous rendre compte que bien que la donnée utilisée dans la fonction main s'appelle value et que la donnée de la fonction foo s'appelle aussi value, il s'agit en réalité de deux données tout à fait différentes. Il y a eu copie de la donnée nommée value dans la fonction main lorsque la fonction foo a été appelée.
Quand on transmet une donnée par référence, on crée en réalité un alias de la donnée transmise au niveau de la fonction appelée.
C'est à dire que, au pire, la donnée sera connue sous un autre nom dans la fonction appelée, mais ce sera basiquement la même donnée qui sera manipulée dans les deux fonctions. C'est à dire que toutes les manipulations que pourra subir la donnée au niveau de la fonction appelées seront ... répercutées sur la donnée de la fonction appelante.
Si nous modifions un tout petit peu le code précédant pour lui donner la forme de
1 2 3 4 5 6 7 8 9 10 11
| void add_two(int & data){
data +=2;
std::cout<<"dans add_two, data = " << data<<"\n";
}
int main(){
int value{5};
std::cout<<"Avant add_two, value = " <<value<<"\n";
add_two(value);
std::cout<<" Apres add_two, value = "<<value<<"\n";
return 0;
} |
après compilation, son exécution provoquera l'affichage
1 2 3
| Avant add_two, value = 5
dans add_twoo, data= 7
Apres add_two, value = 7 |
On remarque donc que, bien que la donnée ne porte plus le même nom dans les deux fonctions (elle s'appelle value dans la fonction main et data dans la fonction foo), c'est, malgré tout la même donnée qui est manipulée, et toutes les modifications subies par la donnée dans la fonction appelée (foo) sont répercutées sur la donnée au niveau de la fonction appelante (main).
Il en va, grosso modo, de même pour les valeurs de retour (avec quelque particularités dont je ne parlerai pas tout de suite ).
Ce qu'il y a d'intéressant, lorsque tu renvoie par référence une référence reçue comme paramètre, c'est que cela te permet de "chaîner les appels".
Tu auras remarqué que le code que j'ai écrit prend la forme de
std::cout<<"une chaine de caractères fixe" << une_variable <<"une autre chaine de caractères fixe";
Ce code aura exactement le même résultat que si j'avais écrit un code proche de
1 2 3
| std::cout<<"une chaine de caractères fixe";
std::cout<<une_variable;
std::cout<<"une autre chaine de caractères fixe"; |
Mais il est beaucoup plus facile de le faire sous la première forme que sous la deuxième, parce que le code est "plus compacte" et que j'ai moins de caractères à écrire au final.
En outre, si tu a un éditeur de textes correct, il affichera les différents éléments avec des couleurs différentes, ce qui te permettra de te rendre compte qu'il y a bel et bien plusieurs éléments distincts. Il n'y aura donc aucun impact sur la facilité avec laquelle "quelqu'un d'autre" pourra comprendre le code. Tous bénef
Enfin, il faut savoir que la classe std::ostream ne peut pas être copiée. Ce qui est normal, car, vu qu'elle intervient dans une hiérarchie de classes, elle a forcément sémantique d'entité (mais cette notion est sans doute très loin de ton niveau actuel ... nous en reparlerons plus tard en cas de besoin ).
Contentons nous donc dans un premier temps de savoir que, si tu essayais de créer une copie d'une donnée de type std::ofstream (de std::cout, par exemple), le compilateur ne serait vraiment pas content et t'enverrait bouler; ce qui justifie ma réponse courte .
(2) Non, parce que std::cout est le nom d'une variable globale, comme std::cin, alors que la signature de fonction doit connaitre le type des données, aussi bien pour ce qui concerne les paramètres attendus que pour ce qui concerne le ... type de retour de la fonction
NOTA: pourrais tu changer le titre de la discussion, par exemple sous la forme "problème d'opérateur", pour qu'il décrive un peu mieux ton problème car " adda issa abdoul razak", ca ne me disait absolument rien
Partager