Conception de Programmes - IUT de Paris - 1ère année Cours 2 – Références et passage de paramètres Les Références –Introduction aux références –Usage classique : passage de paramètres –Les références = type de donnée Le mode de passage des paramètres –Les différents modes –Types de données pour chaque modes –Exemples –Conseils (et plus …)
Conception de Programmes - IUT de Paris - 1ère année Les références En C, les paramètres sont toujours passés par valeur void f(int i) { int a = 10; i = a; } void g(int* i) { int a = 20; *i = a; } void main(void) { int x = 100; f(x); // la valeur de x cout << x; g(&x); // la valeur de &x cout << x; } Mais qu’affiche ce programme ?
Conception de Programmes - IUT de Paris - 1ère année En C++, un nouveau type de passage des paramètres: le passage de paramètre par référence La modification de la valeur d’un paramètre passé par référence est répercutée au niveau de l’appelant void h(int &i) { int a = 30; i = a; } void main(void) { int x = 100; h(x); // une référence sur x cout << x; } Techniquement, c’est l’adresse de la variable fournie en paramètre qui est transmise
Conception de Programmes - IUT de Paris - 1ère année Evolution de la pile d'exécution i "référence" x global main x: 100 entrée dans main global main x: 100 h i: a:30 entrée dans h global main x:30 après le retour de h
Conception de Programmes - IUT de Paris - 1ère année Exemples classiques Paramètres par références void swap(int& a, int& b) { int tmp = a; a = b; b = tmp; } La fonction swap prend en paramètre deux références vers des entiers Les paramètres effectifs d’un appel ne peuvent être que des variables void main() { int x = 10, y = 20; swap(x, y);// x = 20 et y = 10 swap(2, x+y);// error // cannot convert param. 1 from ‘const int' to 'int &' // cannot convert param. 2 from 'int' to 'int &' }
Conception de Programmes - IUT de Paris - 1ère année Paramètres par références vers des constantes struct BigStruct { int tab[10000];... }; void print(const BigStruct& b) { cout << b.nom << … << endl; } Il n’y a aucune contrainte sur les paramètres effectifs. Le compilateur contrôle que le contenu de la variable n’est pas modifié. On cumule les avantages du passage de paramètre par adresse, la facilité d’écriture et les contrôles du compilateur
Conception de Programmes - IUT de Paris - 1ère année void particulier(const int& a) {... } void main() { particulier(1); } Juste avant l’appel de fonction particulier a lieu: L’allocation d’une variable temporaire (sur la pile) Son initialisation avec la valeur 1 Le paramètre passé à la fonction est une référence vers la variable temporaire Au retour de la fonction, la variable temporaire est désallouée.
Conception de Programmes - IUT de Paris - 1ère année Référence rendue par une fonction const int MAX = 10; struct Personne { char nom[20]; int age; }; int& AccesAge(Personne P[], char *nom) { for (int i=0; i<MAX; i++) if (strcmp(P[i].nom, nom)==0) return P[i].age; // problème si le nom est introuvable } void main(void) { Personne Tab[MAX];... AccesAge(Tab, "dupont") = 22; } Faites un schéma de l’évolution de la pile d’exécution
Conception de Programmes - IUT de Paris - 1ère année Un peu plus sur les références Une référence est un nom alternatif pour une variable int i = 10; int& ri = i;// i et ri désigne la même variable int j = ri; // j = 10 ri = 20;// i = 20 Une référence doit être initialisée au moment de sa déclaration et référencera toujours la même variable. int& ri; // erreur, référence non initialisée Une référence peut être assimilé à un pointeur constant. ri++; // ri est inchangée, i est incrémentée
Conception de Programmes - IUT de Paris - 1ère année Références et constantes Une référence peut référencer une constante uniquement si elle est déclarée comme étant une référence vers une constante char& r = 'a';// illégal const char& r = 'a';// légal char c; const char& rc = c;// légal rc = 'a';// illégal
Conception de Programmes - IUT de Paris - 1ère année Un nouveau type de données: référence vers … Ne pas confondre l’opérateur & permettant d ’obtenir l ’adresse d’une variable et le signe & des références De manière générale, à partir de n’importe quel type T, on peut construire les nouveaux types suivants: –T* : pointeur vers une donnée de type T ( int* pi ) –T[] : tableau de données de type T ( char s[256] ) –T& : référence vers une donnée de type T ( int &ri )
Conception de Programmes - IUT de Paris - 1ère année Mode de passage des paramètres Paramètres d’entrée –Donnée dont la valeur est nécessaire au calcul –Cette valeur n’est pas modifiée par le calcul Paramètres de sortie –Donnée dans laquelle est stockée un résultat du calcul –Aucune hypothèse n’est faite sur sa valeur initiale Paramètres d’entrée/sortie –Donnée dont la valeur est nécessaire au calcul –Donnée dans laquelle est stockée un résultat du calcul
Conception de Programmes - IUT de Paris - 1ère année Quel type pour chaque mode ? Paramètres d’entrée –Type de base ( char, int, etc…) : valeur –Structure : référence vers une constante –Tableau : pointeur vers une constante Paramètres de sortie ou d’entrée/sortie –Type de base : référence –Structure : référence –Tableau : pointeur Remarque: dans d’autres langages (Ada, Eiffel), il est possible de différencier les paramètres de sortie de ceux d’entrée/sortie
Conception de Programmes - IUT de Paris - 1ère année Exemple #include const int MAX = 2; struct Personne { char nom[20]; int age; }; // p est un paramètre en entrée void affichePers(const Personne& p) { cout << p.nom << " " << p.age; }
Conception de Programmes - IUT de Paris - 1ère année Exemple (suite) // t est un paramètre en entrée void afficheTab(const Personne t[]) { for(int i=0; i<MAX; i++) { affichePers(t[i]); cout << endl; } // t et n sont des paramètres en entrée // ind est un paramètre en sortie bool recherche(const Personne t[], const char n[], int& ind) { for(ind=0; ind<MAX; ind++) if (strcmp(t[ind].nom, n)==0) return true; return false; }
Conception de Programmes - IUT de Paris - 1ère année Exemple (suite) // p1 et p2 sont des paramètres en entrée/sortie void swap(Personne& p1, Personne& p2) { Personne tmp=p1; p1=p2; p2=tmp; } void main() { Personne tab[MAX] = {{"toto",2}, {"tata",3}}; int i; afficheTab(tab); if (recherche(tab, "tata", i)) cout << "l'age de tata est de " << tab[i].age << endl; swap(tab[0], tab[1]); afficheTab(tab); }
Conception de Programmes - IUT de Paris - 1ère année Conseils Règle absolue: pour chaque fonction –Définir tous les paramètres nécessaires et uniquement ceux-ci –Pour chaque paramètre : Définir son mode (entrée, sortie ou entrée/sortie) En déduire le type C++ Le prototype d’une fonction est une interface entre l’appelant et l’appelé –Les personnes qui écrivent le code de l’appelant et celui de l’appelé ne sont pas nécessairement les mêmes –Le responsable de la fonction doit donner toutes les informations utiles pour se servir de la fonction mais uniquement celles-ci Un bon prototype Une bonne documentation –Bonus : le compilateur peut détecter les erreurs au plus tôt.
Conception de Programmes - IUT de Paris - 1ère année Documentation Fonction recherche Recherche une personne dans un tableau de personnes Synopsis: #include "personne.h" bool recherche(const Personne t[], const char n[], int& ind) Valeur retournée: renvoie true si au moins une personne du tableau t porte le nom n. ind est alors initialisée avec l’indice de la 1ère personne correspondant. Dans le cas contraire, la fonction renvoie false et la valeur de ind n’est pas spécifiée. Pré-requis: t le tableau doit avoir MAX éléments ( MAX est définie dans personne.h ) n la chaîne de caractères doit être terminée par '\0'