Objectifs. Pointeurs : rappels. Fonctions. Pointeurs : suite. Annexes. Jamila Sam. Objectifs. Pointeurs : rappels. Fonctions.



Documents pareils
Cours d initiation à la programmation en C++ Johann Cuenin

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Cours de Programmation Impérative: Zones de mémoires et pointeurs

Java Licence Professionnelle CISII,

Conventions d écriture et outils de mise au point

Cours de C++ François Laroussinie. 2 novembre Dept. d Informatique, ENS de Cachan

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Premiers Pas en Programmation Objet : les Classes et les Objets

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Bases de programmation. Cours 5. Structurer les données

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Claude Delannoy. 3 e édition C++

Le langage C. Séance n 4

Argument-fetching dataflow machine de G.R. Gao et J.B. Dennis (McGill, 1988) = machine dataflow sans flux de données


Algorithmique et Programmation, IMA

Cours d Algorithmique et de Langage C v 3.0

I. Introduction aux fonctions : les fonctions standards

Introduction au langage C

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

Poker. A rendre pour le 25 avril

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

STAGE IREM 0- Premiers pas en Python

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

et Programmation Objet

Chapitre 1 : La gestion dynamique de la mémoire

C++ Programmer. en langage. 8 e édition. Avec une intro aux design patterns et une annexe sur la norme C++11. Claude Delannoy

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

TP1 : Initiation à Java et Eclipse

Utilisation d objets : String et ArrayList

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Analyse de sécurité de logiciels système par typage statique

Le prototype de la fonction main()

Une introduction à Java

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

C++ COURS N 2 : CLASSES, DONNÉES ET FONCTIONS MEMBRES Classes et objets en C++ Membres d'une classe Spécification d'une classe Codage du comportement

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

UE Programmation Impérative Licence 2ème Année

Les structures. Chapitre 3

Programme Compte bancaire (code)

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Cours No 3 : Identificateurs, Fonctions, Premières Structures de contrôle.

ACTIVITÉ DE PROGRAMMATION

Programmer en JAVA. par Tama

Quelques éléments de compilation en C et makefiles

Cours 1: Java et les objets

Java Licence Professionnelle CISII, Cours 2 : Classes et Objets

Présentation du langage et premières fonctions

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Chapitre 2. Classes et objets

Recherche dans un tableau

Plan du cours. Historique du langage Nouveautés de Java 7

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Polymorphisme, la classe Object, les package et la visibilité en Java... 1

COMPARAISONDESLANGAGESC, C++, JAVA ET

Polycopié Cours Programmation Orientée Objet sous Java Programme : Filière SMI S5

Les chaînes de caractères

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

Programmation Objet Java Correction

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Université Paris-Dauphine DUMI2E 1ère année, Applications

TP : Gestion d une image au format PGM

Programmation système I Les entrées/sorties

INF 321 : mémento de la syntaxe de Java

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

Outils pour la pratique

LE LANGAGE C++ ENAC 1997 A. DANCEL

as Architecture des Systèmes d Information

Programmation C++ (débutant)/instructions for, while et do...while

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

UE C avancé cours 1: introduction et révisions

Programmation en C/C++

Un ordonnanceur stupide

TP 1. Prise en main du langage Python

PROJET 1 : BASE DE DONNÉES REPARTIES

Chap III : Les tableaux

La mémoire. Un ordinateur. L'octet. Le bit

Initiation. àl algorithmique et à la programmation. en C

Introduction à MATLAB R

TP, première séquence d exercices.

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

Les structures de données. Rajae El Ouazzani

TD3: tableaux avancées, première classe et chaînes

Arguments d un programme

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Le langage C++ est un langage de programmation puissant, polyvalent, on serait presque tenté de dire universel, massivement utilisé dans l'industrie

SUPPORT DE COURS. Langage C

Exercices sur les interfaces

TD3 - Facturation avec archivage automatisé

Gestion distribuée (par sockets) de banque en Java

Programmation avec des objets : Cours 7. Menu du jour

Transcription:

du cours d aujourd hui suite suite Informatique II : Cours de programmation (C++), & Rappeler ce qu est un pointeur et aborder des exemples d utilisation typiques de ce concept : allocation dynamique, généricité (pointeurs sur des ) Présenter le concept voisin de Haroud Réviser la notion de et apprendre les nouveautés en la matière en C++ (par rapport à C) : Laboratoire d Intelligence Artificielle Faculté I&C Le passage d arguments par La surcharge de Les arguments par Informatique II Cours 2 : et pointeurs 1 / 69 Informatique II Cours 2 : et pointeurs 2 / 69 Les pointeurs : rappel Les pointeurs : rappel (2) suite Une variable est physiquement identifiée de façon unique par son adresse, c est-à-dire l adresse de l emplacement mémoire qui contient sa valeur. Un pointeur est une variable qui contient l adresse d un autre objet informatique. une «variable de variable» en somme pointeur adresse de x suite La déclaration d un pointeur se fait selon la syntaxe suivante : type* identificateur; Cette instruction déclare une variable de nom identificateur de type pointeur sur une valeur de type type. int* x; déclare une variable x qui pointe sur une valeur de type int. L initialisation d un pointeur se fait selon la syntaxe suivante : type* identificateur(adresse); mémoire... 010101010001 0001001110101010 01000... valeur de la variable x Exemples : int* ptr(0); // C++98 int* ptr(&i); En, l initialisation du pointeur à zéro est remplacée par: int* ptr(nullptr); Informatique II Cours 2 : et pointeurs 3 / 69 Informatique II Cours 2 : et pointeurs 4 / 69

suite Opérateurs sur les pointeurs Les deux opérateurs particuliers en relation avec les pointeurs sont : & et *. & est l opérateur qui retourne l adresse mémoire de la valeur d une variable Si x est de type type, int x(3); int* px; px = &x; &x est de type type* (pointeur sur type). px adresse &x x valeur suite Opérateurs sur les pointeurs (2) * est l opérateur qui retourne la valeur pointée par une variable pointeur. Si px est de type type*, (*px) est la valeur de type type pointée par px. px adresse *px int x(3); int* px; x valeur // x est de type entier // px est un pointeur sur entier px = &x; // px pointe sur la variable x cout << *px // affiche la valeur pointee par px << endl; affiche 3. Note : *&i est donc strictement équivalent à i Informatique II Cours 2 : et pointeurs 5 / 69 Informatique II Cours 2 : et pointeurs 6 / 69 suite Allocation de mémoire En C++ comme en C, il y a deux façons d allouer de la mémoire : suite Allocation de mémoire (2) C++ possède deux opérateurs new et delete permettant d allouer et de libérer dynamiquement de la mémoire. ➀ déclarer des variables La réservation de mémoire est déterminée à la compilation : allocation statique ➁ allouer dynamiquement de la mémoire pendant l exécution d un programme. Dans le cas particulier des pointeurs, l allocation dynamique permet également de réserver de la mémoire indépendamment de toute variable : on pointe directement sur une zone mémoire plutôt que sur une variable existante. pointeur = new type; réserve une zone mémoire de type type et met l adresse correspondante dans pointeur. Il est également possible d initialiser l élément pointé directement lors de son allocation : pointeur = new type(valeur);.................................................................. delete pointeur ; Note : Il existe en C++ des structures de données dynamiques comme les tableaux de taille variable (vector) ou les chaînes de caractères de type string qui ont recours à l allocation dynamique (nous les verrons au cours prochain). Informatique II Cours 2 : et pointeurs 7 / 69 libère la zone mémoire allouée au pointeur pointeur. C est-à-dire que cette zone mémoire peut maintenant être utilisée pour autre chose. Il ne faut plus y accéder! (je vous conseille même de faire suivre tous vos delete de l instruction «pointeur = 0;» ou «pointeur = nullptr;» en ) Informatique II Cours 2 : et pointeurs 8 / 69

suite Exemples int* px(0); px = new int; *px = 20; cout << *px << endl; delete px; px = 0;........................................ int* px(0); px = new int(20);........................................ int* px(new int(20)); suite Toujours allouer avant d utiliser! Attention! Si on essaye d utiliser (pour la lire ou la modifier) la valeur pointée par un pointeur pour lequel aucune mémoire n a été réservée, une erreur de type Segmentation fault se produira à l exécution. int* px; *px=20; //! Erreur : aucune allocation faite pour px!! cout << *px << endl; Compilation : OK Execution Segmentation fault Conseil : Toute zone mémoire allouée par un new doit impérativement être libérée par un delete correspondant! ( «garbage collecting») Conseil : Initialisez toujours vos pointeurs. Utilisez 0 si vous ne connaissez pas encore la mémoire pointée au moment de l initialisation : int* px(0); Informatique II Cours 2 : et pointeurs 9 / 69 Informatique II Cours 2 : et pointeurs 10 / 69 Les pointeurs (2) : une analogie Les pointeurs (2) : une analogie suite Un pointeur c est comme la page d un carnet d adresse (sur laquelle on ne peut écrire qu une seule adresse à la fois) : suite Un pointeur c est comme la page d un carnet d adresse (sur laquelle on ne peut écrire qu une seule adresse à la fois) : déclarer un pointeur e.g. int* ptr; affecter un pointeur ptr e.g. ptr = &x; allouer un pointeur ptr e.g. ptr = new int; ajouter une page dans le carnet (mais cela ne veut pas dire qu il y a une adresse écrite dessus!) recopier sur la page ptr l adresse d une maison qui existe déja (mais ptr n est pas la maison, c est juste la page qui contient l adresse de cette maison!) aller construire une maison quelque part et noter son adresse sur la page ptr (mais ptr n est pas la maison!) «libérer un pointeur» ptr (en fait, c est «libérer l adresse pointée par le pointeur» ptr) e.g. delete ptr; Aller détruire la maison dont l adresse est écrite en page ptr. Cela ne veut pas dire que l on a effacé l adresse sur la page ptr!! mais juste que cette maison n existe plus. Cela ne veut pas non plus dire que toutes les pages qui ont la même adresse que celle inscrite sur la page ptr n ont plus rien (mais juste que l adresse qu elles contiennent n est plus valide) Informatique II Cours 2 : et pointeurs 11 / 69 Informatique II Cours 2 : et pointeurs 11 / 69

Les pointeurs (2) : une analogie Notion de réutilisabilité 1) suite Un pointeur c est comme la page d un carnet d adresse (sur laquelle on ne peut écrire qu une seule adresse à la fois) : p1 = p2; On recopie à la page p1 l adresse écrite sur la page p2. Cela ne change rien à la page p2 et surtout ne touche en rien la maison dont l adresse se trouvait sur la page p1! p1 = 0; On gomme la page p1. Cela ne veut pas dire que cette page n existe plus (son contenu est juste effacé) ni (erreur encore plus commune) que la maison dont l adresse se trouvait sur p1 (i.e. celle que l on est en train d effacer) soit modifiée en quoi que ce soit!! Cette maison est absolument intacte! suite #include Informatique II Cours 2 : et pointeurs 11 / 69 Informatique II Cours 2 : et pointeurs 12 / 69 Notion de réutilisabilité 1) Notion de réutilisabilité (2) #include suite z=f(u,v,t); f suite Pourquoi réutiliser plutôt que dupliquer du code (copier/coller) : la duplication rend la mise à jour de ce programme plus difficile : reporter chaque modification de P dans chacune des copies de P elle réduit fortement la compréhension du programme résultant cela augmente inutilement la taille du programme Informatique II Cours 2 : et pointeurs 12 / 69 Informatique II Cours 2 : et pointeurs 13 / 69

Fonction Exemple de fonction suite fonction : portion de programme réutilisable Plus précisément, une fonction est un objet logiciel caractérisé par : un nom identificateur de la «fonction», indiqué lors de sa création ; un corps le programme à réutiliser qui a justifié la création de la fonction ; des arguments (les entrées ) ensemble de d "objets" définis à l extérieur de la fonction dont les valeurs sont potentiellement utilisées dans le corps de la fonction ; un type et une valeur de retour (la sortie ). Le type est indiqué dans le prototype et la valeur est indiquée dans le corps par la commande return. suite int diviseur(int nombre) if ((nombre % 2) == 0) return 2; const double borne_max(sqrt(nombre)); bool premier(true); int valeur_retour(1); for (int i(3); (premier) && (i <= borne_max); i += 2) if (nombre % i == 0) premier = false; valeur_retour = i; return valeur_retour; Informatique II Cours 2 : et pointeurs 14 / 69 Informatique II Cours 2 : et pointeurs 15 / 69 Les «3 facettes» d une fonction Prototypage, Définition suite Résumé / Contrat («prototype») Création / construction («définition») Utilisation («appel») programmeur utilisateur appel accord prototype programmeur concepteur/développeur définition z=f(x,y) double f(double,double); double f(double a,double b) suite Le prototypage est la déclaration de la fonction sans en définir le corps Il sert à définir pour le reste du programme quels sont le nom, les arguments et le type de la valeur de sortie de la fonction. Toute fonction doit être prototypée avant d être utilisée. La définition d une fonction sert à définir (!!) ce que fait la fonction. C est donc la spécification de son corps. Il n est pas nécessaire d avoir défini une fonction avant de l utiliser. La définition d une fonction peut être faite n importe où ailleurs (mais après son prototypage!). La valeur retournée par la fonction est indiquée par l instruction : return valeur; où valeur est une expression ayant le type retourné par la fonction (type dans l exemple précédent) Informatique II Cours 2 : et pointeurs 16 / 69 Informatique II Cours 2 : et pointeurs 17 / 69

Exemple complet Prototypage suite //PROTOTYPE double moyenne(double nombre_1, double nombre_2); // UTILISATION int main () double note1(0.0), note2(0.0); cout << "Entrez vos deux notes : " << endl; cin >> note1 >> note2; cout << "Votre moyenne est : " << moyenne(note1, note2) << endl; //DEFINITION double moyenne(double x, double y) return (x + y) / 2.0; suite Dans les prototypes des, les identificateurs des arguments sont optionnels. En fait, ils ne servent qu à rendre le prototype plus lisible. Dans l exemple précédent, la fonction moyenne() peut donc également être prototypée par : double moyenne (double, double) ; Conseils : Écrivez cependant les noms des arguments dans le prototypage des et choisissez des noms pertinents. Cela augmente la lisibilité de votre code (et donc facilite sa maintenance). Informatique II Cours 2 : et pointeurs 18 / 69 Informatique II Cours 2 : et pointeurs 19 / 69 Prototypage par la définition Arguments, Valeur de Retour suite Si la définition d une fonction est faite avant son utilisation, cette définition peut également servir de prototype. Dans ce cas, le prototypage est fait en même temps que la définition. Par exemple, on peut directement écrire : double moyenne (double x, double y) return (x+y)/2.0 ; main () cout << moyenne(1.0,2.0) << endl ; Conseil : il est cependant préférable de prototyper avant de définir une fonction. On peut, par la suite par exemple déplacer la définition de la fonction, ou bien écrire d autres utilisant cette fonction, etc suite Il est possible de définir une fonction : sans arguments (liste d arguments vide) : int saisie_entier () int i ; cout << "entrez un entier: " ; cin >> i ; return i ; int main () int val(saisie_entier()) ; cout << val << endl ; return 0; Informatique II Cours 2 : et pointeurs 20 / 69 Informatique II Cours 2 : et pointeurs 21 / 69

Arguments, Valeur de Retour (2) suite Il est possible de définir une fonction : sans valeur de retour (void comme type de retour et corps sans return ou avec return;) : void affiche_entiers (int n) for (int i(0); i<n; ++i) cout << i << endl; C / C++ suite En C++, une fonction peut donner des valeurs par à ses arguments lors de son prototypage. Ceux pour lesquels c est le cas ne devront alors pas nécessairement être fournis lors de l appel de la fonction. La syntaxe d un argument avec valeur par est : type identificateur = valeur int main () affiche_entiers(10); return 0; Attention : Les arguments avec valeur par doivent apparaître en dernier dans la liste des arguments d une fonction. Informatique II Cours 2 : et pointeurs 22 / 69 Informatique II Cours 2 : et pointeurs 23 / 69 suite : Exemple void affiche_ligne(char elt, int nb = 5); main() affiche_ligne( * ); affiche_ligne( +, 8); void affiche_ligne(char elt, int nb) for (int i(0); i < nb; ++i) cout << elt; cout << endl; L exécution de ce programme produit l affichage : ***** ++++++++ Lors de l appel affiche_ligne( * ), la valeur par 5 est utilisée ; c est strictement équivalent à affiche_ligne( *, 5) Lors de l appel affiche_ligne( +, 8), la valeur explicite 8 est utilisée. Informatique II Cours 2 : et pointeurs 24 / 69 suite : Remarques Les arguments par se spécifient dans le prototype et non pas dans la définition de la fonction Lors de l appel à une avec plusieurs arguments ayant des valeurs par, les arguments omis doivent être les derniers et omis dans l ordre de la liste des arguments. void f(int i, char c = a, double x = 0.0); f(1) correct (vaut f(1, a,0.0)) f(1, b ) correct (vaut f(1, b,0.0)) f(1,3.0) incorrect! f(1 3.0) incorrect! f(1, b,3.0) correct Informatique II Cours 2 : et pointeurs 25 / 69

Notion de portée : 1. les blocs Notion de portée : 2. local/global suite Les blocs ont en C++ une grande autonomie. Que ce soient des corps de fonction ou non, ils peuvent contenir leurs propres déclarations / initialisations de variables : if (x!= 0.0) double y(0.0); y = 5.0 / x; // ici on ne peut plus utiliser y!! suite les variables déclarées à l intérieur d un bloc sont appelées variables locales (au bloc). Elles ne sont accessibles qu à l intérieur du bloc. les variables déclarées en dehors de tout bloc (même du bloc main()) seront appelées variables globales (au programme). Elles sont accessibles dans l ensemble du programme. Conseil : Ne jamais utiliser de variables globales (sauf peut être pour certaines constantes). La portée d une variable c est l ensemble des lignes de code où cette variable est accessible / est définie / existe / a un sens. Informatique II Cours 2 : et pointeurs 26 / 69 Informatique II Cours 2 : et pointeurs 27 / 69 Règle de résolution de portée : cas des boucles suite En cas d ambiguïté dans le nom, c est-à-dire de plusieurs variables (de portées différentes) portant le même nom, la règle utilisée en C++ est la suivante (règle de résolution de portée) : l objet interne (i.e. «le plus proche») est systématiquement choisi (on parle de «portée locale») Il faut de plus savoir que les arguments d une fonction sont de portée le corps de la fonction Conseil : à éviter au maximum d utiliser plusieurs fois le même nom de variable (sauf peut être pour des variables locales aux boucles : i, j, etc..) suite La déclaration d une variable à l intérieur d une boucle est une déclaration associée au bloc de la boucle. Dans la structure d itération suivante, la variable i est locale à la boucle. for (int i(0); i<10; ++i) cout << i << endl; // ici on NE peut PLUS utiliser i confusion pour le lecteur humain et d autres programmeurs potentiels, ou même en cas de reprise future du code. Informatique II Cours 2 : et pointeurs 28 / 69 Informatique II Cours 2 : et pointeurs 29 / 69

suite / Appel int x, z; main () int x, y;... int y;... x...... y...... z......... y............................................................................. int f(int x); int z; main () int x, y;...... f(y)... int f(int x) int y;...... x... y...... z... suite Évaluation d un appel de fonction Pour une fonction définie par int f(type1 x1, type2 x2,, typen xn) l évaluation de l appel f(arg1, arg2,, argn) s effectue de la façon suivante : ➀ les expressions arg1, arg2,, argn sont évaluées (dans un ordre quelconque!) ➁ les valeurs correspondantes sont affectées aux arguments x1, x2,, xn de la fonction f (variables locales au corps de f) Concrètement, ces deux premières étapes reviennent à faire : x1 = arg1, x2 = arg2,, xn = argn ➂ le programme correspondant au corps de la fonction f est exécuté ➃ l expression suivant la première commande return est évaluée et retournée comme résultat de de l appel. ➄ cette valeur remplace l expression de l appel, i.e. l expression f(arg1, arg2,, argn) Informatique II Cours 2 : et pointeurs 30 / 69 Informatique II Cours 2 : et pointeurs 31 / 69 Évaluation d un appel de fonction (2) Exemple double moyenne (double x, double y) return (x+y)/2.0 ; suite Les étapes ➀ et ➁ n ont bien sûr pas lieu pour une fonction sans arguments. Les étapes ➃ et ➄ n ont bien sûr pas lieu pour une fonction sans valeur de retour (void). L étape ➁ n a pas lieu lors d un passage par (voir plus loin). suite pour la fonction moyenne définie au début du cours, considérons l appel suivant : z = moyenne(1.0 + sqrt(24.0), 12 % 5); ➀ évaluation des expressions passées en arguments : 12 % 5 2 1.0 + sqrt(24.0) 5.89897948557 ➁ affectation des arguments : x = 5.89897948557 y = 2 ➂ exécution du corps de la fonction : rien dans ce cas (le corps réduit au simple return) ➃ évaluation de la valeur de retour (x + y)/2.0 3.94948974278 ➄ replacement de l expression de l appel par sa valeur : z = 3.94948974278; Informatique II Cours 2 : et pointeurs 32 / 69 Informatique II Cours 2 : et pointeurs 33 / 69

Appel : résumé L évaluation de l appel fonctionnel peut être schématisé de la façon suivante : Le passage des arguments par valeur La variable locale associée à un argument passé par valeur correspond à une copie de l argument Les modifications effectuées à l intérieur de la fonction ne sont donc pas répercutées à l extérieur de la fonction. suite int f(int x); main() int y, z...... z = f(y)... int f(int x)...... return (... ) suite void f(int x) x = x + 1 ; cout << "x=" << x ; main () int val(1) ; f(val) ; // CET APPEL VA T-IL CHANGER val?? cout << " val=" << val << endl ; L exécution de ce programme produit l affichage : x=2 val=1 Ce qui montre que les modifications effectuées à l intérieur de la fonction f() ne se répercutent pas sur la variable val associée à l argument x passé par valeur. Informatique II Cours 2 : et pointeurs 34 / 69 Informatique II Cours 2 : et pointeurs 35 / 69 suite Limitation du passage par valeur Si l on souhaite qu une fonction modifie un de ses arguments et que cette modification reste visible après la fin de l exécution de la fonction : void echange(int a, int b) int copie(a); a=b; b=copie; int main() int i(10), j(55); echange(i,j); cout << "Apres: i=" << i << " et j=" << j << endl; return 0; suite Le passage des arguments par Solution C (passage des arguments sous forme de pointeurs) : void echange(int* a, int* b) int copie(*a); *a = *b; *b = copie; int main() int i(10), j(55); // on passe des ADRESSES // en argument echange(&i,&j); cout << "Apres: i=" << i; cout << " j=" << j << endl; return 0; Après l appel de echange i vaut toujours 10 et j, 55! Impossible d interchanger le contenu des deux variables au moyen d une fonction en utilisant le passage par valeur! Informatique II Cours 2 : et pointeurs 36 / 69 Informatique II Cours 2 : et pointeurs 37 / 69

suite Le passage des arguments par Solution C++ (passage des arguments par ) : // Le symbole & fait // toute la difference! void echange(int& a, int& b) int copie(a); a = b; b = copie; int main() int i(10), j(55); echange(i,j); cout << "Apres: i=" << i; cout << " j=" << j << endl; return 0; suite Passages d argument : résumé Soit : int val(1); f(val); valeur (prototype : void f(int x);) : 1 val copie (prototype : void f(int& x);) : 1 x Référence = synonyme pour un identificateur. Ici a et b sont simplement des autres noms pour les variables i et j. x val nom () supplémentaire 1 Informatique II Cours 2 : et pointeurs 38 / 69 Informatique II Cours 2 : et pointeurs 39 / 69 suite Le type Une est un synonyme d identificateur, un autre nom pour un objet existant. La déclaration d une se fait selon la syntaxe suivante : type& nom_reference(identificateur); Après une telle déclaration, nom_reference peut être utilisé partout où identificateur peut l être. Une permet donc de désigner un objet indirectement : int val(1); int& x(val); 1 x val nom () supplémentaire Les s sont très utiles lors du passage d arguments aux, mais aussi parfois pour les valeurs de retour comme nous le verrons par exemple dans le cas de la surcharge d opérateurs au second semestre. suite Attention aux pièges! sémantique de l affectation int i(3); int& j(i); // alias /* i et j sont la * * MEME case memoire */ i = 4; // j AUSSI vaut 4 j = 6; // i AUSSI vaut 6 int i(3); int j(i); // copie /* i et j vivent leur * * vie separement */ i = 4; // j vaut encore 3 j = 6; // i vaut encore 4 sémantique de const int i(3); const int& j(i); /* i et j sont les memes. * * On ne peut pas changer la * * valeur VIA J * * (mais on peut le faire * * par ailleurs). */ j = 12; // NON i = 12; // OUI, et j AUSSI vaut 12! Informatique II Cours 2 : et pointeurs 40 / 69 Informatique II Cours 2 : et pointeurs 41 / 69

suite Spécificités des s Une : doit absolument être initialisée (vers un objet existant) : int i; int& ri(i); // OK int& rj; // NON, la reference rj doit // etre liee a un objet! ne peut être liée qu à un seul objet : int i; int& ri(i); int j(2); ri = j; // ne veut pas dire que ri pointe sur j // mais que i prend la valeur de j! cout << i << endl; // affiche 2 ne peut pas être référencée : int i(3); int& ri(i); int& rri(ri); // NON int&& rri(ri); // NON PLUS on ne peut (donc) pas faire de tableau de s :-( suite r-value references En, il existe en plus des s vers les valeurs transitoires : les r-value references. int&& temp(f()); Cela n est utile que pour des raisons d optimisation (éviter des copies, move semantics) Voir la mini- sur C++11 Informatique II Cours 2 : et pointeurs 42 / 69 Informatique II Cours 2 : et pointeurs 43 / 69 Pourquoi ne pas se contenter des pointeurs? Pourquoi ne pas se contenter des pointeurs? Une c est donc comme un pointeur mais avec quelques «gardes-fous» L usage de permet un style plus concis (le dément explicite n est plus nécessaire). Comparez : suite dans l exemple précédent : echange(int& a, int&b) ne peut être appelée qu avec echange(i,j), où i et j sont des variables déclarées dans le bloc d appel. avec echange(int* a, int* b) rien n empêche l appel où b par exemple ne pointe vers rien de valide! «Utilisez des s quand vous pouvez, des pointeurs quand vous devez.» suite void echange(int* a, int* b) int copie(*a); *a = *b; *b = copie; void echange(int& a, int& b) int copie(a); a = b; b = copie; Le passage par est le mode à privilégier absolument en C++ lorsque l on veut qu une fonction puisse modifier une variable passée en argument Informatique II Cours 2 : et pointeurs 44 / 69 Informatique II Cours 2 : et pointeurs 45 / 69

suite Houlala! GARE AUX CONFUSION! C++ utilise malheureusement deux notations identiques (& et *) pour deux choses différentes! type& id est une sur une variable id dans le passage par d une fonction &id est l adresse de la variable id, par exemple en affectation d un pointeur. CE N EST PAS LA MÊME CHOSE! type* id; déclarare une variable id comme un pointeur sur un type de base type *id (où id est un pointeur) représente le contenu de l endroit pointé par id CE N EST PAS LA MÊME CHOSE! suite Les instructions dans le corps de la fonction dont la finalité n est pas le calcul de la valeur de retour, ou qui modifient des objects extérieurs à la fonction, sont usuellement appelés des effets de bord. int memoire(0); int carre(int a); main () int j; j = carre(5); int carre(int a) // memorise la derniere valeur utilisee memoire = a; return a * a; Informatique II Cours 2 : et pointeurs 46 / 69 Informatique II Cours 2 : et pointeurs 47 / 69 Évitez absolument les effets de bords : c est-à-dire de faire dans une fonction des modifications sur des objets extérieurs à la. Bonne solution : La surcharge des En C++, les types des arguments font partie intégrante de la définition d une fonction. suite int carre(int argument); main () int memoire(0); int j; memoire = 5; j = carre(memoire); int carre(int a) return a * a; suite C / C++ Il est de ce fait possible de définir plusieurs de même nom si ces n ont pas les mêmes listes d arguments : nombre ou types d arguments différents. Ce mécanisme, appelé surcharge des, est très utile pour écrire des «sensibles» au type de leurs arguments c est-à-dire des correspondant à des traitements de même nature mais s appliquant à des entités de types différents. surcharge Le C ne permet pas la surcharge (overloading) de Informatique II Cours 2 : et pointeurs 48 / 69 Informatique II Cours 2 : et pointeurs 49 / 69

La surcharge des : exemple suite void affiche(int x) cout << "entier : " << x << endl; void affiche(double x) cout << "reel : " << x << endl; void affiche(int x1, int x2) cout << "couple : " << x1 << x2 << endl; affiche(1), affiche(1.0) et affiche(1,1) produisent alors des affichages différents. Remarque : void affiche(int x); void affiche(int x1, int x2 = 1); est interdit! ambiguïté suite Chaque appel de fonction ralentit en fait un peu l execution du programme (e.g. passage des arguments). Un moyen d accélérer le passage des arguments est d éviter la copie locale du passage par valeur. On utilisera alors un passage par. Mais comme il s agit d une optimisation et non pas d un vrai passage par, on n autorisera pas la fonction à modifier ses arguments en protègeant la par le mot const. double moyenne (const double& x, const double& y) return (x + y) / 2.0 ; Conseil : utilisez toujours const dans vos passages par sauf si vous voulez vraiment modifier la variable passée par. Informatique II Cours 2 : et pointeurs 50 / 69 Informatique II Cours 2 : et pointeurs 51 / 69 (2) Les suite On peut aussi essayer d éviter le processus même de l appel à la fonction et, lors de la compilation, suggérer au compilateur de mettre la copie complète du corps de la fonction aux endroits de ses appels. Cela se fait en ajoutant le mot réservé inline devant le prototype de la fonction. Du fait que le corps doit être connu au moment de la compilation, on utilise souvent le prototypage par la définition pour les «inline». inline double moyenne (const double& x, const double& y) return (x + y) / 2.0 ; Conseil : utilisez inline avec parcimonie, uniquement pour les très courtes. suite Prototype (à mettre avant toute utilisation de la fonction) : type nom ( type1 arg1,, typen argn [ = valn ] ); type est void si la fonction ne retourne aucune valeur. Définition : type nom ( type1 arg1,, typen argn ) corps return value; valeur : type f(type2 arg); arg ne peut pas être modifié par f (exemple) : void affiche (int arg); void affiche (double arg); void affiche (int arg1, int arg2); : type f(type2& arg); arg peut être modifié par f Informatique II Cours 2 : et pointeurs 52 / 69 Informatique II Cours 2 : et pointeurs 53 / 69

suite sur En fait, les pointeurs, à quoi ça sert? En programmation, les pointeurs servent essentiellement à trois choses : ➀ à permettre à plusieurs portions de code de partager des objets (données,,.. ) sans les dupliquer ➁ à pouvoir choisir des éléments non connus a priori (au moment de la programmation) généricité ➂ à pouvoir manipuler des objets dont la portée ( la durée de vie) dépasse les blocs dans lesquels ils sont déclarés allocation dynamique (moins important en en raison de la move semantic) Important : Il faut toujours avoir clairement à l esprit pour lequel de ces trois objectifs on utilise un pointeur dans un programme! suite sur Comment «pointer sur» un objet? En C++, il existe plusieurs façon de «pointer sur» un objet : les s totalement gérées en interne par le compilateur. Très sûres, donc; mais sont fondamentalement différentes des vrais pointeurs. les «pointeurs classiques» (à la C, build-in pointers), tels que revus dans la première partie du cours les plus puissants (peuvent tout faire) mais les plus «dangereux» les «pointeurs intelligents» (smart pointers) gérés par le programmeur, mais avec des gardes-fous. Il en existe 3 : unique_ptr, shared_ptr, weak_ptr (dans la bibliothèque memory) Présentés l année prochaine les std::functions Note : les pointeurs n existent pas dans tous les langages (e.g. Java). Informatique II Cours 2 : et pointeurs 54 / 69 (dans la bibliothèque functional) pour désigner («pointer sur») des Informatique II Cours 2 : et pointeurs 55 / 69 sur suite sur s const suite sur s const En C++, on peut en fait pointer sur n importe quel objet. On peut en particulier pointer sur des. La syntaxe consiste à mettre (*ptr) à la place du nom de la fonction. Les pointeurs sont un vaste sujet, et il y aurait encore beaucoup à dire Voici quelques thèmes choisis pour ceux souhaitent aller plus loin. Par exemple : double f(int i); est une fonction qui prend un int en argument et retourne un double comme valeur double (*g)(int i); est un pointeur sur une fonction du même type que ci-dessus. On peut maintenant par exemple faire : g=f; puis ensuite : z=g(i); Note : pas besoin du & ni du * dans l utilisation des pointeurs de. Informatique II Cours 2 : et pointeurs 56 / 69 Informatique II Cours 2 : et pointeurs 57 / 69

sur en sur, exemple suite suite sur s const généralise la notion de «pointeur sur fonction» au travers du type function de la bibliothèque functional. #include <functional> function<double(double)> f; double g(double x) return x*x; f = g; z = f(a + b); sur s const Supposons que vous ayez préprogrammé 5 : double f1(double x); double f5(double x); et que vous souhaitiez écrire un programme capable d intégrer l une de ces : do cout << "De quelle fonction voulez-vous calculer " << "l integrale [1-5]? "; cin >> rep; while ((rep < 1) (rep > 5)) Comment manipuler de façon générique la réponse de l utilisateur? avec un pointeur sur la fonction correspondante. Informatique II Cours 2 : et pointeurs 58 / 69 Informatique II Cours 2 : et pointeurs 59 / 69 Le programme complet (C++98) 1/2 Le programme complet (C++98) 2/2 suite sur s const #include <iostream> #include <cmath> double f1(double x) return x*x; double f4(double x) return sqrt(exp(x)); double f5(double x) return log(1.0+sin(x)); suite sur s const case 3: choisie = exp ; break ; case 4: choisie = f4 ; break ; case 5: choisie = f5 ; break ; return choisie; /* Fonction est un nouveau type : pointeur sur des * * prennant un double en argument et retournant un double */ typedef double (*Fonction)(double); Fonction demander_fonction() int rep; Fonction choisie; do cout << "De quelle fonction voulez-vous calculer " << "l integrale [1-5]? "; cin >> rep; while ((rep < 1) (rep > 5)) switch (rep) case 1: choisie = f1 ; break ; case 2: choisie = sin ; break ; Informatique II Cours 2 : et pointeurs 60 / 69 double demander_nombre() double integre(fonction f, double a, double b) f(a) int main () double a(demander_nombre()); double b(demander_nombre()); Fonction choix(demander_fonction()); cout.precision(12); cout << "Integrale entre " << a << " et " << b << " :" << endl; cout << integre(choix, a, b) << endl; return 0; Note : ce programme peut encore être amélioré, notamment en utilisant des tableaux Informatique II Cours 2 : et pointeurs 61 / 69

Le programme complet ( ) et effets de bord suite sur s const Il suffit de remplacer par typedef double (*Fonction)(double); typedef function<double(double)> Fonction; suite sur s const Comme un pointeur contient l adresse mémoire d une valeur, si l on passe un pointeur en argument d une fonction, toute modification faite sur cette valeur à l intérieur de la fonction sera répercutée à l extérieur. = effet de bord Reste cependant une subtilité (avancée!) : certaines de la librairie standard ont plusieurs protoypes (surcharge) et l affectation d une function est dans ce cas ambigue. Par exemple, l affectation du cas 2 : choisie = sin; provoque une erreur (d ambiguité) du compilateur. On est alors obligé de désambiguiser : indiquuer de quel sin il s agit. Cela se fait par : choisie = (double(*)(double)) sin; Exemple (à ne pas suivre : utilisez plutôt le passage par ) : void swap(int* x, int* y) int tmp(*x); *x=*y; *y=tmp; main() int x(3),y(2); cout << x << "," << y << endl; // affiche 3,2 swap(&x, &y); cout << x << "," << y << endl; // affiche 2,3 Informatique II Cours 2 : et pointeurs 62 / 69 Informatique II Cours 2 : et pointeurs 63 / 69 constants et pointeurs sur des constantes constants et pointeurs sur des constantes suite sur s const type const* ptr; (ou const type* ptr) déclare un pointeur sur un objet constant de type type : on ne pourra pas modifier la valeur de l objet au travers de ptr (mais on pourra faire pointer ptr vers un autre objet). suite sur s const int i(2), j(3); int const* p1(&i); int* const p2(&i); cout << i << "," << *p1 << "," << *p2 << endl; // 2,2,2 type* const ptr(&obj); déclare un pointeur constant sur un objet obj de type type : on ne pourra pas faire pointer ptr vers autre chose (mais on pourra modifier la valeur de obj au travers de ptr). Pour résumer : const s applique toujours au type directement précédent, sauf si il est au début, auquel cas il s applique au type directement suivant. // *p1 = 5; /* erreur de compilation : on ne peut pas * modifier au travers de p1 */ *p2 = 5; cout << i << "," << *p1 << "," << *p2 << endl; // 5,5,5 p1 = &j; // p2 = &j; /* erreur de compilation : on ne peut pas * modifier p2 */ cout << i << "," << *p1 << "," << *p2 << endl; // 5,3,5 Informatique II Cours 2 : et pointeurs 64 / 69 Informatique II Cours 2 : et pointeurs 65 / 69

& s (avancés) suite sur s const Déclaration : type* pointeur; Déclaration/Initialisation : type* pointeur(adresse); unique_ptr<type>(new type(valeur)); type& reference(objet); suite sur s const Pointeur sur une constante : type const* ptr; Pointeur constant : type* const ptr(adresse); Adresse d une variable : &variable Accès au contenu pointé par un pointeur : *pointeur Pointeur sur une fonction : type_retour (*ptrfct)(arguments) Allocation mémoire : pointeur = new type; pointeur = new type(valeur); function<type_retour(arguments)> ptrfct Libération de la zone mémoire allouée : delete pointeur (pour les «pointeurs classiques», obligatoire) Informatique II Cours 2 : et pointeurs 66 / 69 Informatique II Cours 2 : et pointeurs 67 / 69 Ce que j ai appris aujourd hui La suite suite sur s const à utiliser les particularités des en C++ : le passage par, la surcharge, les arguments par à utiliser des concepts plus sophistiqués liés aux pointeurs : pointeurs sur des, pointeurs constants ou sur des constantes... à manipuler la notion de, voisine de celle de pointeurs mais un peu plus «sécurisée» Les notions rappelées pour aborder ces thèmes ont été: notions de base sur les pointeurs définition et utilisation d une fonction en C++ mécanismes de passage des arguments suite sur s const Exercices de cette semaine : et pointeurs Le prochain cours : Structures de données avancées : tableaux, tableaux dynamique, structures, chaînes de caractères... Les cours suivants : Le dernier thème "non-objet" : fichiers et entrées/sorties Compilation séparée Les débuts de la programmation orientée-objet notion de portée notion d effets de bord je continue à découvrir les particularités de C++ pour les aspects non-objet du langage. Informatique II Cours 2 : et pointeurs 68 / 69 Informatique II Cours 2 : et pointeurs 69 / 69