Spécificités du C++ (hors POO), références, allocation dynamique de mémoire...

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

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

Claude Delannoy. 3 e édition C++

Cours d Algorithmique et de Langage C v 3.0

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

Introduction au langage C

1.6- Génération de nombres aléatoires

Premiers Pas en Programmation Objet : les Classes et les Objets


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

Introduction à l algorithmique et à la programmation M1102 CM n 3

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

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

Programme Compte bancaire (code)

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

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

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

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

Programmation en C/C++

I. Introduction aux fonctions : les fonctions standards

Génie Logiciel I. Cours VI - Typage statique / dynamique, fonctions virtuelles et classes abstraites, flots d entrées / sorties, et string

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

et Programmation Objet

Conventions d écriture et outils de mise au point

TP : Gestion d une image au format PGM

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

Département Automatisation et Informatisation Année Programmation en C++ Institut des Sciences et Techniques de l Ingénieur d Angers

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

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

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

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

INFO-F-105 Language de programmation I Séance VI

Le langage C++ (partie I)

Algorithmique et Programmation, IMA

Notions fondamentales du langage C# Version 1.0

Introduction au pricing d option en finance

Les structures. Chapitre 3

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

Rappels Entrées -Sorties

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Java Licence Professionnelle CISII,

Représentation d un entier en base b

Plan Pédagogique du cours

Programmation stochastique

as Architecture des Systèmes d Information

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

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

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

COMPARAISONDESLANGAGESC, C++, JAVA ET

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

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

ALGORITHMIQUE ET PROGRAMMATION ORIENTEE OBJET

Programmation en Java IUT GEII (MC-II1) 1

Cours 1: Java et les objets

Une introduction à Java

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Programmer en JAVA. par Tama

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

SUPPORT DE COURS. Langage C

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

Les chaînes de caractères

TP 1. Prise en main du langage Python

Introduction à l héritage en C++

Le langage C. Séance n 4

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

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

Introduction à la programmation concurrente

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

STS SE. FreeRTOS. Programmation réseau WIFI. Programmation réseau. Socket Tcp. FlyPort smart Wi-Fi module

STAGE IREM 0- Premiers pas en Python

Notes du cours 4M056 Programmation en C et C++ Vincent Lemaire et Damien Simon

INF111. Initiation à la programmation impérative en C amini/cours/l1/inf111/ Massih-Reza Amini

Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application

Le langage C. Introduction, guide de reference

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)

Tp 1 correction. Structures de données (IF2)

Introduction à C++ et à wxwidgets

ACTIVITÉ DE PROGRAMMATION

Informatique Générale

Algorithmes et Programmes. Introduction à l informatiquel. Cycle de vie d'un programme (d'un logiciel) Cycle de vie d'un programme (d'un logiciel)

Avertissement : Ce cours suppose la connaissance et la maîtrise du langage C CONTENU DU COURS BIBLIOGRAPHIE

Utilisation d objets : String et ArrayList

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

Programmation en langage C d un µcontrôleur PIC à l aide du compilateur C-CCS Sommaire

Cours de Systèmes d Exploitation

Traduction des Langages : Le Compilateur Micro Java

IRL : Simulation distribuée pour les systèmes embarqués

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

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

Présentation du langage et premières fonctions

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

Aide mémoire UML & Java 1ère partie : Introduction. marc.lemaire@u-cergy.fr

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Langage Éric Guérin 5 octobre 2010

IUT ANNECY Département Mesures Physiques Cours d informatique Initiation au langage C

Chapitre 10. Les interfaces Comparable et Comparator 1

Le Langage C++ Patrick TRAU - ULP IPST version du 02/10/05

1 Définition et Appel d une fonction. V. Phan Luong. Cours 4 : Fonctions

Langage Java. Classe de première SI

Transcription:

Fiche 2 Spécificités du C++ (hors POO), références, allocation dynamique de mémoire... Le C++ est un langage dit orienté objet (OO) conçu à partir du langage C. De ce fait la plupart des fonctionalités du C restent utilisables en C++. Nous abordons ici les spécifités du C++ par rapport au C qui ne relèvent pas de la programmation orientée objet (POO). Il s agit notamment des références des opérateurs d allocation dynamique de mémoire new et delete de la déclaration des variables des arguments de fonctions par défaut de la surdéfinition de fonction du type bool des espaces de noms Les nouveaux opérateurs de cast et les fonctions en ligne (inline), autres spécifités du C++, ne sont pas abordées ici. 2.1 Les références 2.1.1 Rappels sur les adresses et les pointeurs Une variable prend de l espace en mémoire. Par exemple, un entier i occupe 4 octets. L endroit où se trouve la variable i en mémoire est l adresse de i. Inversement, l adresse en notation héxadécimale 0x22ff74A correpond aux 4 octets soit 32 bits 01001001001001010010101010010101010 de l entier i. L adresse d une variable est donnée par &nom_de_la_variable. De même qu une variable peut contenir des valeurs, un pointeur est un conteneur d adresse. Au cours de sa vie, une variable peut valoir 12 puis 222 puis -27 alors qu un pointeur désignera l adresse en mémoire soit, successivement, 0x21fd740 puis 0x22ff74A puis 0x22aa23B. Un pointeur possède lui aussi un type, à savoir que l adresse se réfère à un type de données (par exemple un pointeur sur un entier). En outre, un pointeur occupe lui aussi de l espace

mémoire. Il prend 2 octets qui servent à conserver l adresse. On peut donc créer des pointeurs sur des pointeurs La déclaration d un pointeur se présente de la façon suivante // Déclaration type_du_pointeur *nom_pointeur; tandis que son affectation s écrira // Affectation nom_pointeur = adresse_de_la_variable; Exemple: int i; int *pt_i; pt_i = &i; 2.1.2 Définition des références Une référence permet de donner deux noms différents pour une seule et même case mémoire. Le symbole de la référence est & (le même que pour l adresse d une variable). On déclare une référence de cette façon int i = 0; // j est une référence de i int &j = i; // j et i représentent alors la même case mémoire Une référence nécessite obligatoirement une initialisation vers une variable qu elle va référencer, l instruction int &j; n est pas correcte et sera rejetée par le compilateur. En outre, une référence pointe toujours vers le même objet; on ne pourra donc pas changer sa destination. Les références servent rarement directement. Elle sont le plus souvent utilisées dans les fonctions en argument ou en valeur de retour. Le principal intérêt de la référence est qu elle permet de laisser le compilateur mettre en œuvre les instructions adéquates pour le transfert par adresse, c est à dire qu une réference est explicitée lors de la déclaration et la définition d une fonction et ensuite la variable est utilisée via son nom sans se soucier de préciser si on veut utiliser son adresse ou sa valeur comme c est le cas pour les pointeurs (via les symbole * ou &). 2.1.3 Références et fonctions rappel sur les fonctions Syntaxe type_retourné nom_fonction(..., type_argument nom_argument,...) // Opérations avec les arguments return variable_retournée; Exemple : double norme(const double a, const double b) const double resultat = std::sqrt(a*a +b*b); return resultat; // ou directement return std::sqrt (a*a + b*b); 2

Prototype de fonction type_retourné nom_fonction(..., type_argument nom_argument,...); Le prototype indique au compilateur que la fonction prototypée existe, mais que sa définition interviendra après son appel. Un prototype de fonction est une déclaration de fonction. Exemple: double norme(const double a, const double b); // NB attention au point virgule const double x = 2.5, y = 3.4; cout << norme(x,y) << endl; double norme(const double a, const double b) const double resultat = std::sqrt(a*a +b*b); return resultat; 2.1.4 Modification de variables via l utilisation d une fonction Une fonction en C/C++, dans son utilisation la plus commune i.e. argument transmis par valeur comme dans l exemple précédent, ne modifie aucune variable en argument. La fonction utilise ses arguments pour créer, par exemple, une nouvelle valeur qu elle retourne (la valeur resultat dans notre exemple). Plus précisément, lors de l appel d une fonction, par exemple norme (4, 5), Norme crée deux variables locales a et b et réalise les opérations de recopie suivantes: a = 4 et b = 5. De même, en déclarant deux variables double x = 4.1; et double y = 5.6;, l appel à la fonction norme (x, y) entrainera la création de deux nouvelles variables locales a et b en assignant leurs valeurs a = x et b = y. La fonction ne possède que les valeurs de x et y; ainsi utilisée, elle ne pourra jamais modifier x et y. 2.1.5 Argument transmis par adresse Imaginons qu au lieu de transmettre des valeurs à la fonction, on transmette des adresses ou des pointeurs qui contiennent une adresse. La fonction crée toujours deux variables a et b au moment de son appel et copie dans ces deux variables les adresses utilisées lors de l appel de la fonction. La fonction norme se réécrit ainsi double norme(const double *a, const double *b) const double resultat = std::sqrt((*a)*(*a) + (*b)*(*b)); return resultat; que l on appelera au sein du programme principal via l instruction suivante const double x = 2.5, y = 3.4; cout << norme(&x, &y) << endl; On ne travaille plus avec les valeurs de x et y qui sont ponctuellement 4.1 et 5.6 mais avec les données de x et y i.e. les 01001 qui composent x et y. On peut donc modifier ces données au sein de la fonction, car on travaille directement avec elles et non avec leurs simples valeurs recopiées. La solution proposée présente néanmoins quelques inconvénients d une part, la syntaxe est lourde en raison de l emploi de l opérateur * devant les paramètres, 3

d autre part, la syntaxe est dangereuse lors de l appel de la fonction, puisqu il faut systématiquement penser à utiliser l opérateur & devant les paramètres. Un oubli devant une variable de type entier et la valeur de l entier est utilisée à la place de son adresse dans la fonction appelée. Le C++ permet de résoudre ces problèmes à l aide des références 2.1.6 Argument transmis par référence Comme nous venons de le rappeler, en langage C, les arguments et la valeur de retour d une fonction sont transmis par valeur y compris lors de la transmission par adresse puisque les valeurs de pointeurs sont recopiées. Le C++ peut entièrement prendre en charge la transmission par adresse à travers l utilisation des références. Le principal intérêt de la notion de référence est qu elle laisse le compilateur mettre en œuvre les mécanismes adaptés au transfert par adresse. Il n est plus alors nécessaire de passer par des pointeurs. L utilisateur de la fonction (qui n est pas nécessairement celui qui l a écrite) n a, dès lors, plus à connaitre la nature des arguments à transmettre (une variable ou son adresse). L exemple précédent devient double norme(const double &a, const double &b) const double resultat = std::sqrt(a*a + b*b); return resultat; const double x = 2.5, y = 3.4; cout << norme(x,y) << endl; Dans l instruction double norme(const double &a, const double &b); la notation double &a signifie que a est une information de type double transmise par référence. On notera que, dans la fonction norme, est utilisé le symbole a pour désigner cette variable et non l opérateur d indirection *. Cette amélioration est extrêmement importante du point de vue des performances. Il est ainsi fortement recommandé de passer par référence tous les paramètres dont la copie peut prendre beaucoup de temps tels que les tableaux et plus encore les instances de classe (en pratique, seuls les types de base du langage pourront être passés par valeur). Le gain en temps du fait de ne plus créer de copie d objet, devient non négligeable a fortiori, lors d appels successifs de la fonction. 2.2 Allocation dynamique de mémoire via les opérateurs new et delete Si nous considérons le cas d un tableau statique, sa dimension doit être connue du compilateur au moment même de la compilation. Une déclaration telle que unsigned int n = 0; std::cin >> n; double tableau[n]; n est pas correcte du fait que le compilateur ne connaît pas, au préalable, l espace mémoire nécessaire à l allocation. 4

Dans l hypothèse où la taille d un objet n est connue que lors de l exécution du programme, il est alors inévitable d allouer dynamiquement de la mémoire, c est-à-dire de réserver de la mémoire alors que le programme est en cours d exécution. En langage C, la gestion dynamique de mémoire fait appel aux fonctions malloc et free. Si comme toute fonction standard leur implémentation est possible en C++, leur utilisation demeure lourde et non adaptée à la programmation orientée objet. Le C++ propose deux nouveaux opérateurs new et delete pour gérer l allocation dynamique de mémoire. 2.2.1 Utilisation de l opérateur new Comme malloc en langage C, new alloue une certaine quantité de mémoire pour le tableau et renvoie un pointeur sur le début du tableau. La syntaxe est la suivante type * pt_tableau = new type[nbr_element]; Exemple int *pt_tableau; unsigned int n_dimension_tableau = 666; pt_tableau = new int[n_dimension_tableau]; 2.2.2 Utilisation de l opérateur delete[] De même que free libère l espace alloué par malloc en langage C, delete[] libère l espace mémoire alloué par l opérateur new. Ainsi, delete[] pt_tableau; restaurera l espace mémoire précédemment alloué pour 666 valeurs entières. De manière générale, l utilisation de l opérateur new implique nécessairement l utilisation de sa contrepartie delete. Dans le cas contraire, des fuites de mémoire, i.e. de la perte de mémoire libre au profit d objet qui n existent plus, sont à craindre et peuvent, sous certaines conditions, rendre le système totalement inutilisable (cf exemples du diaporama Spécificités du C++ (hors POO), références, allocation dynamique de mémoire... ). 2.3 Utilisation de la bibliothèque standard du C++ (cas des fichiers d en-tête) La grande majorité des fichiers d en-tête utilisés dans le langage C est présente et utilisable en C++. Toutefois, leur définition a été optimisée pour les besoins du C++. Dans la pratique lors de l inclusion des fichiers d en-tête, les fichiers tels que math.h, time.h seront remplacés par les fichiers cmath, ctime... En règle générale, les fichiers d en-tête issus de la bibliothèque standard abandonnent l extension.h. 2.4 Déclaration de variables En C, il faut d abord déclarer les variables, puis ensuite les instructions. Ainsi, les déclarations sont regroupées en début de fonction ou de bloc. En C++, il est possible de déclarer les variables n importe où, tant qu elle sont déclarées avant les instructions qui les utilisent. À titre d exemple double x;... x=...; int y = sqrt(x);... 5

est possible en C++. Les déclarations lors des initilisations des instructions structurées (for, while, switch,...) sont aussi possibles, comme ici for (int i = 0; i < 10; i++)... 2.5 Argument par défaut Le C++ permet d affecter des valeurs par défauts aux arguments dans les prototypes de fonctions ( déclarations de fonctions). Le prototype s écrit alors : type nom_fonction(..., type argument = valeur_par_défaut); Soit void initialisation(double abs, double ord = 5.6) que l on appelera de la façon suivante initialisation(4); // valeur 5.6 par défaut pour ord En l absence de second argument, le compilateur assigne la valeur 5.6 à la variable ord. Lorsqu une déclaration prévoit des valeurs par défauts, les arguments concernés doivent obligatoirement être les derniers dans la liste. 2.6 Surdéfinition de fonction En C++ deux fonctions peuvent porter le même nom a à condition qu elles n aient pas les mêmes arguments. Le compilateur se charge d appeler la bonne fonction suivant le contexte c est-à-dire au vu de la liste d arguments donnée lors de l appel. Ainsi double fonction_lambda(int, double, char); et double fonction_lambda(double); seront deux fonctions différentes grâce aux différents types d arguments déclarés. Exemple, le programme suivant a de façon générale, on parle de surdéfinition ou surcharge lorsqu un même symbole peut avoir deux significations différentes en fonction du contexte. 6

#include<iostream> using namespace std; double fonction_lambda(int, double, char); double fonction_lambda(double); int i = 2; double a = 3.3; char c = 'b'; double res = fonction_lambda(i,a,c); cout << "res = " << res << endl; res = fonction_lambda(a); cout << "res = " << res << endl; return 0; double fonction_lambda(int i, double a, char c) cout << "fonction lambda numéro 1, int = " << i << " double = " << a << " char = " << c << endl; return a; double fonction_lambda(double a) cout << "fonction lambda numéro 2, double = " << a << endl; return a*2; affiche fonction lambda numéro 1, int = 2 double = 3.3 char = b res = 3.3 fonction lambda numéro 2, double = 3.3 res = 6.6 2.7 Le type bool Le type bool permet de déclarer des variables booléennes, c est à dire des variables à deux états, vrai et faux (true et false). Les conversions implicites définies sont : de bool en numérique i.e. true devenant 1 et false devenant 0, de numérique (y compris flottant) vers bool à savoir que toute valeur non nulle devient true et zéro est équivalent à false. Exemple d utilisation 7

#include<iostream> using namespace std; bool neutre = true; bool masse = false; if (neutre &&!masse) cout << "je suis un photon" << endl; else cout << "je ne peux pas être un photon" << endl; masse = true; if (neutre &&!masse) cout << "je suis un photon" << endl; else cout << "je ne peux pas être un photon" << endl; return 0; 2.8 Les espaces de noms Les espaces de noms sont des zones de déclaration qui permettent de délimiter la recherche des noms des identificateurs par le compilateur. Leur but est essentiellement de regrouper les identificateurs et d éviter les conflits de noms entre plusieurs parties d un même projet. À titre d exemple, lorsque l on doit utiliser plusieurs bibliothèque dans un programme, on peut être confronté au problème dit de pollution de l espace des noms, à savoir qu un même identificateur peut très bien avoir été utilisé par plusieurs bibliothèques. Ce type de conflit provient du fait que le C++ ne fournit qu un seul espace de noms de portée globale. Grâce aux espaces de noms non globaux, ce type de problème peut être évité. Il s agit donc de donner un nom à un espace de déclarations, en procédant ainsi namespace nom_bibli // Déclaration usuelles de fonctions, variables... Pour se référer aux identificateurs définis dans cet espace de noms, on utilise l instruction using using namespace nom_bibli; que l on place à un niveau global, i.e. entre l inclusion des fichiers d entête et le corps du programme. Les identificateurs de la librairie standard (les opérateurs d entrée/sortie de flux cout, cin notamment) sont ainsi définis dans l espace de noms std. Ainsi, chaque programme principal débutera généralement par #include <iostream> // librairie standard de gestion des flux d'entrées/sortie... using namespace std; // corps du programme principal Dans le cas où plusieurs espaces de noms sont utilisés, certains comportant des identificateurs identiques, on pourra lever l ambiguïté en utilisant l opérateur de portée :: en remplaçant, par exemple, cout par std::cout Exemple d utilisation 8

#include<iostream> //utilisation de l'espace de nom standard pour ``cout'' using namespace std; namespace utl void dump() cout << "utl::dump" << endl; namespace io void dump() cout << "io::dump" << endl; // Utilisation de l'espace de nom io using namespace io; // Par défaut, io::dump() dump(); // Précision de l'espace de nom utl::dump(); io::dump(); 9