Problème fonctions C++

Résolu/Fermé
Bebert450 Messages postés 17 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 15 septembre 2008 - 24 févr. 2008 à 13:29
mamiemando Messages postés 33264 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 13 septembre 2024 - 25 févr. 2008 à 13:24
Bonjour,
J'ai une fois de plus besoin de vous! ^^

1)
int max1(int a , int b){
if(a>b) return a;
else return b;
}

int & max2(int & a , int & b){
if(a>b) return a;
else return b;
}

int & max3(int a , int b){
if(a>b) return a;
else return b;
}


Pourriez-vous m'expliquer ce que fait exactement la fonction max2 par rapport à la fonction max1?
J'ai cru comprendre qu'elle retournait une adresse mais :

2)
J'ai vu ensuite que:
max1(x,y) n'est pas une lvalue
max2(x,y) est une lvalue!

Mais pourquoi?? Je croyais que les adresses ne pouvaient pas être en partie gauche d'une affectation!

Et une dernière chose:
Pourquoi la fonction max3 est incorrecte?

Merci d'avance pour vos réponses!

3 réponses

mamiemando Messages postés 33264 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 13 septembre 2024 7 777
24 févr. 2008 à 20:29
Ce ne sont pas des adresses mais des références. Syntaxiquement parlant tout se passe comme si tu manipulait le type de l'objet (ici int), mais informatiquement parlant tout se passe comme si tu manipulais le pointeur. Ainsi :
#include <iostream>

void incrementer1(int x){
  ++x;
}

void incrementer2(int & x){
  ++x;
}

void incrementer3(int *x){
  ++*x;
}

int main(){
  int x = 28;
  std::cout << x << std::endl; // 28
  incrementer1(x); // x n'est modifié qu'à l'intérieur du scope de incrementer1
  std::cout << x << std::endl; // 28
  incrementer2(x); 
  std::cout << x << std::endl; // 29
  incrementer3(x);
  std::cout << x << std::endl; // 30
  return 0;
}

En effet en C et en C++ une fonction duplique ses paramètre en mémoire (et c'est pour ca que les références et les pointeurs permettent de manipuler efficacement des grosses structures, car on ne recopie que l'adresse). En l'occurrence il ne faut jamais retourner une référence (ou une adresse) d'une variable locale à ta fonction, car cette valeur sera détruite dès que la fonction sera quitté.

De manière plus générale dès que tu sors d'un bloc { ... } que ce soit une boucle ou une fonction, tu quitte ce qu'on appelle un scope (horizon) et toutes les variables locales à ce scope sont détruites. C'est typiquement ce qui se passe dans max3 : a et b sont des recopies des variables a et b du main (donc des variables locales à la fonction), et tu retournes une référence sur a ou b, qui seront toutes deux désallouées à la fin de max3.

C'est pour ca qu'il faut soit que les variables devant "survivre" à un scope doivent soit provenir d'un scope plus global (comme dans max1), ou doivent être allouées dans la fonction via un new ou un malloc (le pointeur en tant que variable locale sera détruit, mais pas la variable à cette adresse).

En toute rigueur ta fonction max2 s'écrit ainsi (car elle ne modifie pas les entiers a et b) :
const int & max2(const int & a,const int & b){
  if (a<b) return b;
  return a;
}

Note que tu peux aussi directement utiliser std::max après avoir inclu le header <cmath>

Bonne chance
1
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
24 févr. 2008 à 21:29
Bonjour,

Très belle explication.

Une correction minuscule dans le main:
  incrementer3(&x);

Comme le paramètre est explicitement un pointeur il faut passer explicitement une adresse.

M.
0
Bebert450 Messages postés 17 Date d'inscription samedi 23 février 2008 Statut Membre Dernière intervention 15 septembre 2008
24 févr. 2008 à 22:26
Oh!! Un très très grand MERCI!!!
J'ai confondu adresse et référence!!
Encore merci!!


( Ayant un gros trou au niveau de la notion de référence j'ai regardé ce qu'un internaute avait expliqué sur un autre site, si cela intéresse quelqu'un voilà le lien:
https://forum.hardware.fr/hfr/Programmation/reference-sujet_8503_1.htm )
0
mamiemando Messages postés 33264 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 13 septembre 2024 7 777
25 févr. 2008 à 13:24
Merci pour la remarque Mahmah, effectivement j'ai oublié le & ;-)
Heureuse d'avoir pû t'aider bebert

Bonne continuation à tout les deux
0