Conception de Programmes - IUT de Paris - 1ère année Quelques éléments du langage C++ Les références La surcharge de fonctions Les fonctions « en ligne » Les fonctions d’allocation mémoire
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; }
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 Techniquement, c’est l’adresse de la variable fournie en paramètre qui est transmise 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; }
Conception de Programmes - IUT de Paris - 1ère année 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 ) & et * ont une écriture préfixée et [] a une écriture suffixée. [] est prioritaire par rapport à * et à & –int * t[10] : t est un tableau de 10 pointeurs d’entiers –int (*p)[10] : p est un pointeur sur un tableau de 10 entiers
Conception de Programmes - IUT de Paris - 1ère année 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. Une référence peut être assimilé à un pointeur constant. ri++; // rr est inchangée, i est incrémentée Une référence peut être initialisée comme référençant une constante uniquement si cela est explicitement indiqué char& rc = ‘a’; // illégal const char& rc = ‘a’; // légal
Conception de Programmes - IUT de Paris - 1ère année Utilisations classiques des références Paramètres par références void swap(int& a, int& b) { int tmp = a; a = b; b = tmp; } Attention: les paramètres effectifs ne peuvent être que des variables contre-exemples : swap(2, 3) et swap(a+b, c*d) Paramètres par références vers des constantes void print(const BigStruct& b) { cout << b.nom << … << endl; } Il n’y a aucune contrainte sur les paramètres effectifs. On cumule les avantages du passage de paramètre par adresse et la facilité d’écriture. Enfin, le compilateur contrôle que le contenu de la variable n’est pas modifié.
Conception de Programmes - IUT de Paris - 1ère année Cas particulier void particulier(const int& a) {... } particulier(1); L’appel de fonction provoque: L’allocation d’une variable temporaire Son initialisation avec la valeur 1 L’appel de la fonction avec en paramètre 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 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[10];... AccesAge(Tab, «dupont») = 22; }
Conception de Programmes - IUT de Paris - 1ère année La surcharge de fonctions Lorsque plusieurs fonctions effectuent la même tâche sur des objets de type différent, il est souhaitable de leur donner le même nom. C’est déjà le cas pour les opérateurs arithmétiques sur les entiers et les réels. Exemple: void print(int); // affiche un entier void print(const char *); // affiche une chaîne
Conception de Programmes - IUT de Paris - 1ère année Lorsqu’une fonction f est appelée, le compilateur cherche à déterminer quelle fonction de nom f est invoquée. Ce choix est réalisé en comparant le nombre et le type des paramètres effectifs avec le nombre et le type des paramètres formels. Le principe est d’invoquer le fonction ayant la « meilleure » correspondance d’arguments (des conversions implicites peuvent intervenir). Exemple void print(double); void print(float); print(1L); // invoque print(long) print(1.0); // invoque print(float) print(1); // erreur 2 candidats?
Conception de Programmes - IUT de Paris - 1ère année Deux fonctions ne peuvent être distinguées par le type de la valeur retournée. La surcharge de fonction peut être employée pour réaliser l’effet d’un argument par défaut. Exemple void print(int value, int base) { … } void print(int value) { print(value, 10); }
Conception de Programmes - IUT de Paris - 1ère année Les fonctions « en ligne » Le mot clé inline précédant une définition de fonction indique au compilateur qu’il peut essayer d’expanser en ligne les appels de celle-ci plutôt que de la coder et d’utiliser les mécanismes d’appel standard. Il permet d’optimiser les performances de vos programmes Exemple inline fac(int i) { return (i<2) ? i : i*fac(i-1); }
Conception de Programmes - IUT de Paris - 1ère année Selon les compilateurs, un appel à fac(6) peut être expansé en la constante 720 ou en 6*5*4*3*2*1 ou encore en un appel classique de fac(6). inline n’affecte en rien la signification de l’appel de fonction et en particulier le contrôle de type.
Conception de Programmes - IUT de Paris - 1ère année Les fonctions d’allocation mémoire L’allocation dynamique et la désallocation de mémoire sont réalisées respectivement par les opérateurs new et delete. L’opérateur new prend en paramètre un nom de type et rend un pointeur vers la zone mémoire allouée ( 0 en cas d’échec). L ’opérateur delete prend en paramètre un pointeur retourné par new ou un pointeur nul. Dans le premier cas, delete libère la zone mémoire, dans le second, il est sans effet.
Conception de Programmes - IUT de Paris - 1ère année Exemple: int *pi = new int; *pi = 12; delete pi; new et delete peuvent aussi être employés pour créer des tableaux: char *s = new char[strlen(nom)+1]; strcpy(s, nom); delete[] s;