Vous êtes sur la page 1sur 457

Proprit de Client ePagine <3437341@epagine.

fr>
customer 26505 at Tue Feb 15 02:49:55 +0100 2011
Vincent Gouvernelle
C
+
+
L
E

G
U
I
D
E

D
E

S
U
R
V
I
E
V. Gouvernelle
LE GUI DE DE SURVI E
C
++
L ESSENTI EL DU CODE ET DES COMMANDES
Ce Guide de sur vie est le compagnon indispensable
pour programmer en C++ et ut iliser ef cacement les
bibliot hques st andard STL et BOOST, ainsi que QT,
wxWidget et SQLit e. Cet ouvrage prend en compt e la
fut ure norme C++0x.
CONCIS ET MANIABLE
Facile t ranspor t er, facile ut iliser nis les livres
encombrant s !
PRATIQUE ET FONCTIONNEL
Plus de 150 squences de code pour programmer
rapidement et ef cacement en C++.
Vincent Gouvernelle est ingnieur en informat ique, diplm
de l ESIL Marseille, et t it ulaire d un DEA en informat ique.
Il t ravaille act uellement chez Sescoi R&D, socit dit rice de
logiciels spcialiss dans la CFAO (concept ion et fabricat ion
assist e par ordinat eur).
Niveau : Int ermdiaire / Avanc
Cat gorie : Programmat ion
Con gurat ion : Mult iplat e-forme
LE GUI DE DE SURVI E
C
++
L ESSENTI EL DU CODE ET DES COMMANDES
Pearson Education France
47 bis, rue des Vinaigriers
75010 Paris
Tl. : 01 72 74 90 00
Fax : 01 42 05 22 17
www.pearson.fr
ISBN : 978-2-7440-4011-5
2281-GS C++.indd 1 11/05/09 15:56:39
C++
Vincent Gouvernelle
Pearson Education France a apport le plus grand soin la ralisation de ce livre
afin de vous fournir une information complte et fiable. Cependant, Pearson
Education France nassume de responsabilits, ni pour son utilisation, ni pour les
contrefaons de brevets ou atteintes aux droits de tierces personnes qui pourraient
rsulter de cette utilisation.
Les exemples ou les programmes prsents dans cet ouvrage sont fournis pour
illustrer les descriptions thoriques. Ils ne sont en aucun cas destins une utili-
sation commerciale ou professionnelle.
Pearson Education France ne pourra en aucun cas tre tenu pour responsable
des prjudices ou dommages de quelque nature que ce soit pouvant rsulter de
lutilisation de ces exemples ou programmes.
Tous les noms de produits ou marques cits dans ce livre sont des marques dposes
par leurs propritaires respectifs.
Publi par Pearson Education France
47 bis, rue des Vinaigriers
75010 PARIS
Tl. : 01 72 74 90 00
www.pearson.fr
Relecteurs techniques : Philippe Georges et Yves Mettier
Collaboration ditoriale : Jean-Philippe Moreux
Ralisation PAo : La B.
Tous droits rservs
Aucune reprsentation ou reproduction, mme partielle, autre que celles prvues
larticle L. 122-5 2 et 3 a) du code de la proprit intellectuelle ne peut tre faite
sans lautorisation expresse de Pearson Education France ou, le cas chant, sans le
respect des modalits prvues larticle L. 122-10 dudit code.
ISBN : 978-2-7440-4011-5
Copyright 2009
Pearson Education France
1 Bases hrites du langage C 1
Hello world en C 1
Commentaires 3
Types fondamentaux 4
Types labors 6
Structures conditionnelles 9
Structures de boucle 12
Sauts 14
Fonctions 15
Prprocesseur 16
Oprateurs et priorit (C et C++) 18
2 Bases du langage C++ 23
Hello world en C++ 23
Les mots-cls 24
Les constantes 25
Dclarations de variables 27
Les nouveaux types de variables du C++ 29
Conversion de type C 32
Conversion avec static_cast 33
Conversion avec const_cast 34
Conversion avec reinterpret_cast 35
Conversion avec dynamic_cast 36
Surcharge 37
Les espaces de noms 40
Incompatibilits avec le C 42
Lier du code C et C++ 44
Embarquer une fonction 46
Constantes usuelles 46
Jah|c dcs maIcrcs
Iv L++
3 Pointeurs et rfrences 47
Crer et initialiser un pointeur 48
Accder aux donnes ou fonctions membres 49
Crer et utiliser une rfrence 50
Dclarer un pointeur sur un tableau 50
Dclarer un pointeur sur une fonction 54
Passer un objet en paramtre par pointeur/rfrence 57
4 Classes et objets 59
Ajouter des donnes des objets 60
Lier des fonctions des objets 62
Dterminer la visibilit de fonctions
ou de donnes membres 64
Expliciter une instance avec le pointeur this 67
Dfnir un constructeur/destructeur 68
Empcher le compilateur de convertir
une donne en une autre 70
Spcifer quune fonction membre
ne modife pas lobjet li 72
Rendre une fonction/donne membre
indpendante de lobjet li 73
Comprendre le changement de visibilit
lors de lhritage 74
Comprendre les subtilits de lhritage multiple 78
Empcher la duplication de donnes
avec lhritage virtuel 79
Simuler un constructeur virtuel 80
Crer un type abstrait laide du polymorphisme 82
Utiliser lencapsulation pour scuriser un objet 85
Obtenir des informations de types dynamiquement 86
Transformer un objet en fonction 88
v Jah|c dcs maIcrcs
5 Templates et mtaprogrammation 95
Crer un modle de classe rutilisable 96
Crer une bibliothque avec des templates 99
Utiliser un type indirect dans un template 101
Changer limplmentation par dfaut fournie
par un template 102
Spcialiser partiellement limplmentation
dun template 104
Spcialiser une fonction membre 105
Excuter du code la compilation 106
Crer des mta-oprateurs/mtabranchements 108
Avantages et inconvnients de la mtaprogrammation 111
6 Gestion de la mmoire 113
Rserver et librer la mmoire 113
Redfnir le systme dallocation mmoire 114
Simuler une allocation dobjet une adresse connue 115
Traiter un chec de rservation mmoire 116
Dsactiver le systme dexception lors de lallocation 119
Optimiser lallocation avec un pool mmoire 120
7 Exceptions 123
Principe 123
Transmettre une exception 127
Expliciter les exceptions 129
Utiliser ses propres implmentations
des fonctions terminate() et unexpected() 131
Utiliser les exceptions pour la gestion des ressources 132
Exceptions de la STL 134
vI L++
8 Itrateurs 137
Les diffrents concepts 138
Comprendre les iterator_traits 140
Calculer la distance entre deux itrateurs 142
Dplacer un itrateur vers une autre position 144
Comprendre les itrateurs sur fux dentre/lecture 145
Comprendre les itrateurs sur fux de sortie/criture 146
Utiliser les itrateurs de parcours invers 146
Utiliser les itrateurs dinsertion 148
Utiliser les itrateurs dinsertion
en dbut de conteneur 149
Utiliser les itrateurs dinsertion
en fn de conteneur 150
9 Conteneurs standard 151
Crer un conteneur 152
Ajouter et supprimer dans un conteneur squentiel 153
Parcourir un conteneur 154
Accder un lment dun conteneur 156
Crer et utiliser un tableau 158
Crer et utiliser une liste chane 160
Crer et utiliser une fle double entre 161
Crer et utiliser une pile 163
Crer et utiliser une queue 164
Crer et utiliser une queue de priorit 165
Crer et utiliser un ensemble 166
Crer et utiliser une table associative 167
Crer et utiliser une table de hachage 170
Connatre la complexit des fonctions membres
des conteneurs 173
vII Jah|c dcs maIcrcs
10 Chanes de caractres 177
Crer une chane 178
Connatre la longueur dune chane 180
Comparer des chanes 180
changer le contenu de deux chanes 181
Rechercher une sous-chane 182
Extraire une sous-chane 184
Remplacer une partie dune chane 185
Insrer dans une chane 187
Concatner des chanes 188
Effacer une partie dune chane 189
Lire des lignes dans un fux 190
11 Fichiers et fux 193
Ouvrir un fchier 194
Tester ltat dun fux 195
Lire dans un fchier 197
crire dans un fchier 200
Se dplacer dans un fux 201
Manipuler des fux 202
Manipuler une chane de caractres comme un fux 205
crire dans une chane de caractre comme
dans un fux 206
Lire le contenu dune chane comme avec un fux 206
12 Algorithmes standard 209
Calculer la somme des lments dune squence 214
Calculer les diffrences entre lments conscutifs
dune squence 215
Chercher la premire occurrence de deux lments
conscutifs identiques 217
vIII L++
Rechercher un lment dans une squence 218
Copier les lments dune squence dans une autre 219
Copier les lments dune squence dans une autre
en commenant par la fn 221
Copier les n premiers lments dune squence
dans une autre 222
Compter le nombre dlments correspondant
une valeur donne 223
Compter le nombre dlments conformes
un test donn 224
Tester si deux squences sont identiques 225
Chercher la sous-squence dlments tous gaux
un certain lment 226
Initialiser une squence 228
Chercher le premier lment tel que 228
Chercher le premier lment parmi 229
Appliquer une fonction/foncteur sur
tous les lments dune squence 230
Initialiser une squence laide dun gnrateur
de valeurs 231
Tester si tous les lments dune squence
sont dans une autre 232
Calculer le produit intrieur (produit scalaire
gnralis) de deux squences 234
Initialiser les lments dune squence
avec une valeur (en lincrmentant) 235
Transformer une squence en tas et lutiliser 236
Comparer lexicographiquement deux squences 238
Chercher le premier/dernier endroit o insrer
une valeur sans briser lordre dune squence 241
Fusionner deux squences tries 243
Rcuprer le plus petit/grand lment 245
Rcuprer le plus petit/grand lment dune squence 246
Trouver le premier endroit o deux squences diffrent 247
IX Jah|c dcs maIcrcs
Gnrer la prochaine plus petite/grande permutation
lexicographique dune squence 248
Faire en sorte que le nime lment soit le mme
que si la squence tait trie 250
Trier les n premiers lments dune squence 251
Copier les n plus petits lments dune squence 252
Calculer une somme partielle gnralise
dune squence 253
Couper la squence en deux en fonction dun prdicat 254
Calculer x
i
(fonction puissance gnralise) 256
Copier alatoirement un chantillon dune squence 257
Copier alatoirement un sous-chantillon
(de n lments), en prservant leur ordre dorigine 258
Mlanger les lments dune squence 259
Supprimer certains lments dune squence 260
Copier une squence en omettant certains lments 262
Remplacer certains lments dune squence 263
Inverser lordre de la squence 264
Effectuer une rotation des lments de la squence 264
Chercher une sous-squence 265
Construire la diffrence de deux squences tries 268
Construire lintersection de deux squences tries 270
Construire la diffrence symtrique des
deux squences tries 272
Construire lunion de deux squences tries 273
Trier une squence 274
changer le contenu de deux variables, itrateurs
ou squences 275
Transformer une (ou deux) squences en une autre 276
Supprimer les doublons dune squence
(dans ou lors dune copie) 278
Copier laide du constructeur par copie 281
Initialiser laide du constructeur par copie 282
X L++
13 BOOST 285
Mettre en forme des arguments selon une chane
de formatage 286
Convertir une donne en chane de caractres 289
Construire et utiliser une expression rgulire 291
viter les pertes mmoire grce aux pointeurs
intelligents 295
Crer des unions de types scurises 300
Parcourir un conteneur avec BOOST_FOREACH 304
Gnrer des messages derreur pendant le processus
de compilation 306
14 Programmation multithread avec QT 311
Crer un thread 311
Partager des ressources 312
Se protger contre laccs simultan
une ressource avec les mutex 313
Contrler le nombre daccs simultans
une ressource avec les smaphores 316
Prvenir le compilateur de lutilisation
dune variable dans plusieurs threads 318
15 Base de donnes 319
Savoir quand utiliser SQLite 321
Crer et utiliser une base avec linterprteur SQLite 328
Crer/ouvrir une base (SQLite) 331
Lancer une requte avec SQLite 335
Fermer une base (SQLite) 337
Crer une table (requte SQL) 338
Accder aux donnes dune table (requte SQL) 347
Dfnir un environnement ODBC (wxWidgets) 349
Se connecter une base (wxWidgets) 350
Crer la dfnition de la table et louvrir (wxWidgets) 352
XI Jah|c dcs maIcrcs
Utiliser la table (wxWidgets) 355
Fermer la table (wxWidgets) 356
Fermer la connexion la base (wxWidgets) 357
Librer lenvironnement ODBC (wxWidgets) 358
16 XML 359
Charger un fchier XML 360
Manipuler des donnes XML 363
Annexes
A Bibliothques et compilateurs 369
Compilateurs 369
IDE et RAD 370
Bibliothques 372
Bibliothques dominante graphique 379
Utilitaires 382
B Les ajouts de la future norme C++ (C++0x) 385
Variable locale un thread 386
Unicode et chanes littrales 386
Dlgation de construction 388
Hritage des constructeurs 389
Constructeur et destructeur par dfaut 392
union tendue 394
Oprateurs de conversion explicites 395
Type numration fort 395
Listes dinitialisation 396
Initialisation uniformise 397
Type automatique 399
Boucle for ensembliste 400
Syntaxe de fonction unife 401
XII L++
Concepts 402
Autorisation de sizeof sur des membres 406
Amlioration de la syntaxe pour lutilisation
des templates 407
Template externe 407
Expressions constantes gnralises 408
Les variadic templates 410
Pointeur nul 411
Tuple 412
Lambda fonctions et lambda expressions 414
C Conventions dappel x86 417
Convention dappel cdecl 419
Convention dappel pascal 421
Convention dappel stdcall 422
Convention dappel fastcall 422
Convention dappel thiscall 423
Index 425
XIII Jah|c dcs maIcrcs
propos de lauteur
Vincent Gouvernelle est ingnieur en informatique,
diplm de lESIL Marseille, et titulaire dun DEA en
informatique. Aprs une priode consacre lenseigne-
ment et la recherche, au cours de laquelle il a particip
des travaux sur la paramtrisation de surfaces au sein du
CNRS et du BRGM, il sest tourn vers le monde de
lindustrie. Chez Gemplus, il a travaill sur la personnalisa-
tion des cartes puce et lcriture de drivers optimiss
pour le chiffrement de donnes. Puis au sein de Coretech
International, maintenant fliale de Think3, il revient sa
premire spcialit, la CAO, dans le domaine de la conver-
sion et la correction de modles. Il travaille aujourdhui
chez Sescoi R&D, socit ditrice de logiciels de CFAO.
InIroducIon
Il y a longtemps que je souhaitais runir toutes les infor-
mations relatives aux algorithmes et lutilisation de la
bibliothque standard (STL) et de BOOST. Je me suis dit
quil tait temps de passer lacte lorsque loccasion ma
t donne dcrire ce livre. Lobjectif de la collection
Guide de survie auquel ce dernier appartient est de four-
nir au monde informatique lquivalent des aide-mmoire
linguistiques que lon emmne avec soi ltranger. Ainsi,
cet ouvrage nest pas un simple dictionnaire de fonctions
ou de mots-cls : un effort particulier a t fait pour mettre
en situation chacun deux afn de vous permettre den
exploiter tout le potentiel dans le contexte qui est le vtre.
Les squences de codes (relatives aux bibliothques stan-
dard et BOOST) fournies dans ce livre fonctionnent
avec les compilateurs mentionns dans le tableau ci-des-
sous. La liste nest bien entendu pas exhaustive. Pour ce
qui est des parties employant wxWidget et QT, il sufft de
recourir une plate-forme disposant de ces bibliothques.
Je voudrais remercier les personnes sans qui cet ouvrage
ne serait pas. Pour tout le temps que je nai pas pu leur
consacrer pendant la rdaction de ces pages, je remercie
mon pouse Audrey et mes trois enfants. Merci galement
Patricia Moncorg de la confance quelle ma accorde
pour la ralisation de ce projet, aux relecteurs techni-
ques Philippe Georges et Yves Mettier et au correcteur
Jean-Philippe Moreux. Merci enfn Yves Bailly qui fut le
premier mencourager dans cette aventure.
XvI L++
Jespre que cet ouvrage comblera vos attentes de program-
meur, que vous soyez dbutant ou chevronn.
Compilateurs
P|aIc-formc

Lomp|aIcurs
Windows Visual C++ (7.1 avec SP1 aka 2003,
8.0 aka 2005, 9.0 aka 2008), Intel C++ (10.1),
Comeau C++ (4.3), MingGW, Cygwin
Linux GCC (3.4, 4.0, 4.1, 4.2, 4.3), Intel C++
(8.1, 9.0, 9.1, 10.0), QLogic (3.1),
Sun Compiler (5.9, 5.10 avec stdcxx)
Mac OS X GCC 4 (pour PowerPC ou Intel)
HP-UX GCC 4.2, HP C/aC++, HP aCC
IBM AIX IBM XL C/C++ (10.1)
True64 Compaq C++ (7.1)
Sun Solaris Sun C++ (5.7, 5.8, 5.9), GCC (3.4)
1
8ascs hcrIccs
du |angagc L
Le langage C++ est une volution du langage C. De ce
fait, une partie de la syntaxe est commune ces deux lan-
gages. Ce chapitre rsume rapidement ces points com-
muns quelque peu amliors au passage. Pour plus de
renseignements sur le langage C, vous pouvez vous rfrer
au Guide de survie Langage C dYves Mettier (Pearson,
2007).
Hello world en C
#include <stdio.h>
int main(int argc, char* argv[])
{
printf(Hello world!);
return 0;
}
La premire ligne est une inclusion dun fchier den-tte
de la bibliothque C standard. Cela permet dutiliser la
fonction printf() pour crire le message Hello world!
2 LhAPIJL 1 8ascs hcrIccs du |angagc L
sur la console. La deuxime ligne correspond au point
dentre standard de tout programme C (et C++), cest--
dire que cette fonction est automatiquement appele lors
du lancement du programme. Notez toutefois que le
nommage et les paramtres de ce point dentre peuvent
varier suivant les systmes. Par exemple, Windows a ajout
le point dentre suivant :
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nShowCmd);
Enfn, le return 0 ; indique que le programme sest
droul sans erreur.
Compiler avec gcc
Pour compiler cet exemple, vous pouvez utiliser gcc en
ligne de commande. Par exemple avec mingw ou cygwin
sous Windows, ou toute autre version de gcc (disponibles
sous GNU/Linux, Unix, Mac OS X, etc.) :
gcc helloworld.c o helloworld.exe
Loption c permet de compiler un fchier source et
de crer un fchier objet, rutilisable par la suite.
Loption I permet dajouter des chemins de recher-
che supplmentaires pour les fchiers den-tte.
Loption lbibliotheque permet de linker avec la
bibliotheque donne.
Loption L permet dajouter des chemins de recher-
che supplmentaires pour les bibliothques.
8
Pour plus de simplicit, il existe aussi des environne-
ments intgrs pour le compilateur GNU. Je vous
invite jeter un il sur lexcellent DevCPP (www.
bloodshed.net/devcpp.html disponible pour Win-
dows), CodeBlocks (www.codeblocks.org, disponible
pour Windows, Linux et Mac OS X) ou encore
Anjuta (anjuta.sourceforge.net disponible pour
GNU/Linux).
Compiler avec Microsoft Visual C++
Ouvrez lenvironnement de dveloppement et lais-
sez-vous guider par les assistants de cration de projet.
Pour cet exemple, choisissez une application en mode
console.
Commentaires
/* commentaire C
possible sur plusieurs lignes */
// commentaire C++ sur une seule ligne
Les commentaires C commencent avec une barre oblique
et un astrisque /* et fnissent par un astrisque et une
barre oblique */. Leur contenu peut staler sur plusieurs
lignes et commencer ou fnir en milieu de ligne.
Le commentaire C++ commence ds lapparition de
deux barres obliques // et fnit automatiquement la fn
de la ligne.
LommcnIarcs
4 LhAPIJL 1 8ascs hcrIccs du |angagc L
Types fondamentaux
char caractere;
short entier_court;
int entier;
long entier_long;
foat fottant_simple_precision;
double fottant_double_precision;
signed Type v;
unsigned Type v;
void
Le langage C (et donc C++) comprend de nombreux
types de nombres entiers, occupant plus ou moins de bits.
La taille des types nest que partiellement standardise : le
standard fxe uniquement une taille minimale et une
magnitude minimale. Les magnitudes minimales sont
compatibles avec dautres reprsentations binaires que le
complment deux, bien que cette reprsentation soit
presque toujours utilise en pratique. Cette souplesse
permet au langage dtre effcacement adapts des pro-
cesseurs trs varis, mais elle complique la portabilit des
programmes crits en C/C++.
Chaque type dentier a une forme signe (pouvant repr-
senter un nombre positif ou ngatif, communment appe-
ls nombres relatifs ) et une forme non signe (ne
pouvant reprsenter que des nombres positifs commun-
ment appels nombres naturels ). Par dfaut, les types
entiers sont signs, rendant le qualifcateur signed optionnel.
Le type char est un type entier comme les autres, mis
part le fait que le standard ne prcise pas sil est sign ou
non par dfaut.
5
Modle de donnes et taille des entiers (en bits)
Modc|c

shorI

nI

|ong

ponIcur
LP32 16 16 32 32
ILP32 16 32 32 32
LP64 16 32 64 64
ILP64 16 64 64 64
Limite des types fondamentaux (modle ILP32)
Jypc

Ja||c mn max
(ocIcIs)

char 1 128 127


unsigned char 1 0 255
short 2 32 768 32 767
unsigned short 2 0 65 535
int 4 2 147 483 648 2 147 483 647
unsigned int 4 0 4 294 967 295
long 4 2 147 483 648 2 147 483 647
unsigned long 4 0 4 294 967 295
long long 8 92 233 720 368 547 758 079 223 372 036 854 775 807
unsigned long long 8 0 18 446 744 073 709 551 615
foat 4 10
255
10
255
double 8 10
2047
10
2047
Jypcs fondamcnIaux
8 LhAPIJL 1 8ascs hcrIccs du |angagc L
Info
Le mot-cl register permet dindiquer au compilateur duti-
liser un registre du processeur. Ceci nest quune indication
fournie au compilateur et non une garantie.
Le type void est utile pour le type pointeur sur type
inconnu void* et pour la dclaration de procdure (une
fonction retournant void est une procdure).
Types labors
struct NomStructure { };
union NomUnion { };
enum NomEnum { };
Type *pointeur;
Type tableau[taille];
Type fonction(parametres);
typedef Type nouveauNom;
typedef Type (*MonTypeDeFonction)();
Le C++ a apport son lot damlioration quant la
manire de dclarer de nouveaux types struct, union et
enum. Il sufft maintenant dutiliser le nom de la structure
ainsi dfnie sans devoir systmatiquement rpter le mot-
cl qui la prcde. Il nest plus besoin de recourir de
recourir un alias (typedef) pour parvenir au mme rsultat.
Cest cette syntaxe allge qui est prsente ici.
Les structures (struct) permettent de regrouper plusieurs
variables dans une sorte de groupe et de les rendre ainsi
indissociables, comme sil sagissait dun nouveau type.
1
Dans ce cas, le nom utilis pour chaque variable dans le
bloc devient le moyen daccder celle-ci.
struct Personne
{
char *nom, *prenom;
int age;
};
Personne personne = { Alain, Dupont, 54 };
personne.age = 35;
Les unions de type (union) permettent de voir une mme
donne (binaire) de diffrentes manires. La syntaxe est la
mme que les struct mais son objectif est diffrent.
union IP
{
unsigned int adresse;
struct { unsigned char a,b,c,d; };
};
IP masque;
masque.adresse = 0; // masque.a, .b, .c et .d == 0
masque.a = 255;
masque.b = 255;
masque.c = 255; // masque <=> 255.255.255.0
printf(%X\n, masque.adresse); // => affche FFFFFF00
Les numrations (enum) permettent dassocier des noms
des valeurs entires. Seul le type int est support par le
langage (la future norme C++0x lvera cette limitation).
Elles permettent ainsi de rendre votre code source beaucoup
plus lisible et mieux contrl par le compilateur (par exem-
ple lors dun switch sur une valeur de type numration, le
compilateur gnre un warning si aucune clause default
Jypcs c|ahorcs
8 LhAPIJL 1 8ascs hcrIccs du |angagc L
nest prsente alors que toutes les valeurs de lnumration
ne sont pas prsentes).
enum Etat { Vrai = 1, Faux = 0, Inconnu = -1 };
Par dfaut, toutes les valeurs se suivent dans lordre crois-
sant (si aucune valeur nest mentionne), en commenant
par la valeur zro. Lexemple suivant illustre ce mca-
nisme :
enum Nombre { Zero, Un, Deux, Quatre = 4, Cinq, Sept = 7,

Huit, Neuf };
Les crochets [] permettent de crer des tableaux (de taille
fxe).
int vecteur[3]; // trois entiers
int matrice[3][3]; // neuf entiers
Le mot-cl typedef permet de crer des alias sur dautres
types afn de pouvoir les utiliser plus facilement ou bien
den crer de nouveau en leur donnant ainsi un nouveau
nom.
typedef double Reel; // un rel de IR et cod

en double
typedef Reel Vecteur[3]; // vecteur de IR3
typedef Reel Matrice[3][3]; // matrice de transformation
Vecteur v,v2;
Matrice m;
v[0] = 3.0; v[1] = 5.0; v[2] = 1.0;
m[0][0] = 1.0 ; /**/ m[2][2] = 1.0;
0
Structures conditionnelles
if (test)
instruction;
if (test)
instruction;
else
instruction;
switch (instruction)
{
case valeur1:
instruction;
[ break; ]
case valeur2:

[ default:
[ instruction;
[ break; ]
]
]
}
Les structures conditionnelles permettent dexcuter une
instruction ou une autre en fonction dun test. Les paren-
thses entourant le test sont obligatoires. Un test est une
instruction dont la valeur est entire ou boolenne. Dans
le cas dune valeur entire, toute valeur non nulle est
considre comme tant vraie.
SIrucIurcs condIonnc||cs
10 LhAPIJL 1 8ascs hcrIccs du |angagc L
Lorsque linstruction excuter (pas celle du test mais
celle choisie en fonction du test) est un bloc de code (entre
accolade { }), il ne faut pas mettre de point-virgule aprs
celui-ci. Le code suivant lillustre sur un if :
if (test)
{
// bloc1
}
else
{
// bloc 2
}
La structure conditionnelle switch est une structure de
branchement. Les valeurs utilises pour les points dentre
des branchements (case) doivent tre des constantes et ne
peuvent pas tre des chanes. Lorsquun point dentre est
choisi par le test, lexcution se poursuit cet endroit et ne
sort du switch que lorsquun break est rencontr (et pas
lors du prochain case).
AIIcnIon
Il est interdit deffectuer une dclaration de variable dans un
case. Si vous navez pas dautre choix (pour une variable
temporaire), faites-le alors dans un bloc dinstruction. Mais ce
dernier ne peut pas contenir de case.
int i = ;
switch (i)
{
case 1:
case 2: // si i==1 ou i==2, on se retrouve ici
{
11
// on utilise un bloc si besoin de dclarer des

variables temporaires
int j = ;
i += 3 * j;
}
break;
case 3: // si i==3, on se retrouve l
i += 4;
if ( une_fonction_test(i) )
break; // si une_fonction_test(i) est vraie, on

fnit le switch
default: // si i<1 ou i>3
// ou que le test dans le cas 3 tait faux
// on se retrouve ici
i /= 3;
}
Oprateurs de comparaison
Symho|c SgncaIon
a == b Vrai si a est gal b
a != b Vrai si a est diffrent de b
a < b Vrai si a est infrieur b
a > b Vrai si a est suprieur b
a <= b Vrai si a est infrieur ou gal b
a <= b Vrai si a est suprieur ou gal b
SIrucIurcs condIonnc||cs
12 LhAPIJL 1 8ascs hcrIccs du |angagc L
Oprateurs logiques
Symho|c SgncaIon
a && b Vrai si a et b sont vrais
a
||
b Vrai si a ou b est vrai (lun, lautre ou les deux)
! a Vrai si a est faux
Oprateurs binaires
Symho|c SgncaIon
a & b ET binaire
a
|
b OU binaire
a ^ b OU EXCLUSIF binaire
Structures de boucle
while (instruction)
instruction;
for ( initialisation ; test; incrment )
instruction;
do
{
instruction;
}
while (test);
break;
continue;
18
Dans tous les cas, linstruction est excute tant que le test
est vrai. Il est possible de modifer le cours de lexcution
de linstruction lorsque celle-ci est un bloc, laide des
mots-cls continue et break :
continue interrompt lexcution du bloc et revient au
test de la structure de boucle ;
break interrompt lexcution du bloc et sort de la struc-
ture de boucle ;
lorsque plusieurs structures de boucle sont imbriques,
ces sauts se rfrent la boucle dans laquelle ils se trou-
vent, et pas aux niveaux suprieurs.
Le code ci-aprs montre comment crire une boucle for
avec un while. La dfnition de bloc entourant le code est
ncessaire pour lcriture de son quivalence avec while,
car en C++ linitialisation est locale la structure de
boucle for.
{
initialisation;
while (test)
instruction;
}
La structure do while permet de garantir que linstruc-
tion est excute au moins une fois. Cest un peu comme
si la mme instruction apparaissait avant et dans un while
traditionnel, comme dans lexemple suivant :
instruction;
while (test)
instruction;
SIrucIurcs dc houc|c
14 LhAPIJL 1 8ascs hcrIccs du |angagc L
Sauts
tiquette:
goto tiquette;
Les sauts permettent de sauter dun endroit un autre
dans le fl dexcution des instructions dun programme.
Les tiquettes peuvent tre dotes de tout nom respectant
les mmes contraintes syntaxiques que celles dun identi-
fcateur.
Il nest pas possible deffectuer des sauts en dehors dune
fonction. En revanche, il est possible deffectuer des sauts
en dehors et lintrieur des blocs dinstructions sous cer-
taines conditions (voir lavertissement ci-aprs). Si au
terme dun saut, on sort de la porte dune variable, celle-
ci est dtruite. Enfn, il est impossible de faire un saut dans
un bloc try {} (voir le Chapitre 7 consacr aux excep-
tions).
AIIcnIon
Les sauts sont fortement dconseills. Vous avez certainement
dj entendu ou entendrez certainement que lon peut toujours
sen passer. Cela est vrai, quelques exceptions prs. Toutefois,
leur utilisation rend parfois le code plus lisible. Si vous pensez
quil est lgitime de les utiliser, ne vous en privez pas. Mais
nen abusez pas pour autant, car ils cachent certains piges,
surtout avec le C++ ! En effet, si la dclaration de saut se
trouve aprs une dclaration, cette dclaration ne doit pas
contenir dinitialisations et doit tre un type simple (comme
les variables, les structures ou les tableaux). Vous laurez donc
compris, lutilisation de sauts avec des classes peut se rvler
dlicate.
15
Fonctions
type identifcateur(paramtres)
{
// instructions
}
return [ instruction ];
Les paramtres dune fonction sont de la forme type
variable ou type variable = valeurParDefaut, spars par
une virgule. Attribuer une valeur par dfaut nest possible
que pour le (ou les) dernier(s) paramtre(s conscutifs). Si
le type de retour dune fonction est void, alors il sagit
dune procdure.
La valeur de retour dune fonction est donne par lins-
truction return. Cette instruction fait sortir immdiate-
ment de la fonction (ou de la procdure).
Info
Il est possible dcrire des fonctions acceptant un nombre
variable de paramtres grce au fchier den-tte stdarg.h. Le
code ci-aprs montre un exemple. Sachez toutefois quun tel
code nest pas toujours portable et que limplmentation de
cette fonctionnalit varie suivant les compilateurs.
#include <stdarg.h>
double somme(int quantite, ...)
{
double res = 0.0;
va_list varg;
va_start(varg, quantite);
while (quantite-- != 0)
res += va_arg(varg, double);
FoncIons
18 LhAPIJL 1 8ascs hcrIccs du |angagc L
va_end(varg);
return res;
}
La fonction printf() utilise cette technique. Le nombre, lor-
dre et le type des arguments sont indiqus par le premier para-
mtre correspondant la chane de formatage des donnes.
Prprocesseur
// instructions
#include fchier
#include <fchier>
#defne NOM code
#defne NOM(a [, ]) code
#undef NOM
#if test
#ifdef NOM // quivalent #if defned NOM
#ifndef NOM // quivalent #if not defned NOM
#elif test // C89
#else
#endif
#pragma // C89
#error Message
#warning Message
#line numro [fchier]
11
// constantes
__FILE__
__LINE__
__FUNCTION__ // alternative: __func__
__DATE__
__TIME__
__cpluplus
La directive #include permet dinclure le fchier men-
tionn cet endroit. Lorsque le nom est entre guillemets,
le fchier spcif est recherch dans le rpertoire courant
dabord, puis de la mme manire quavec les crochets. Si
le nom de fchier est entre crochets, le fchier est recher-
ch dans les rpertoires (ou dossiers) spcifs dans les
options dinclusion (-I avec g++) puis dans les chemins de
recherche des en-ttes du systme. Le fchier inclus est lui
aussi trait par le prprocesseur.
Le prprocesseur dfnit un certain nombre de constan-
tes :
__LINE__ donne le numro de la ligne courante ;
__FILE__ donne le nom du fchier courant ;
__DATE__ renvoie la date du traitement du fchier par le
pr-processeur ;
__TIME__ renvoie lheure du traitement du fchier par le
pr-processeur ;
__cpluplus est dfni lors dune compilation en C++. Il
permet de distinguer les parties de code crites en C++
de celles crites en C. En principe, la valeur dfnie
correspond la norme du langage supporte par le
compilateur. Par exemple, pour la norme de novembre
1997, la valeur sera 199711L.
Prcproccsscur
18 LhAPIJL 1 8ascs hcrIccs du |angagc L
AsIucc
Pour convertir un paramtre de macro, il est parfois ncessaire
dimbriquer deux macros pour obtenir un rsultat fonctionnant
correctement. Cest le cas par exemple lors de la transforma-
tion dun paramtre en sa chane de caractres correspondante
(par linstruction #). Le code suivant montre comment sen
sortir dans ce cas :
#defne TO_STR1(x) #x
#defne TO_STR(x) TO_STR1(x)
La syntaxe ## permet de concatner deux paramtres. Le code
suivant permet dobtenir un nom unique. Cette macro, utilise
plusieurs fois sur une mme ligne, gnrera le mme nom.
#defne UNIQUE_NAME2(name,line) name##line
#defne UNIQUE_NAME1(name,line) UNIQUE_NAME2(name,line)
#defne UNIQUE_NAME(name) UNIQUE_NAME1(name,__LINE__)

Les directives de compilation sont couramment utilises
pour la protection des fchiers den-tte contre les inclu-
sions multiples :
#ifndef MON_HEADER
#defne MON_HEADER
// inclus une seule fois
#endif
Oprateurs et priorit (C et C++)
Il est parfois diffcile de se souvenir de lordre de priorit
des oprateurs entre eux. Voici donc une liste les rassem-
blant de la plus haute priorit (on commence par valuer
ceux-ci) la plus basse (le compilateur fnira par ceux-l).
10
Si toutefois vous aviez un doute, ou tout simplement parce
que vous trouvez cela plus lisible, nhsitez pas utiliser les
parenthses () pour forcer lordre dvaluation.
Un groupe rassemble les oprateurs ayant mme priorit,
cest--dire que leur valuation se fait dans lordre de lec-
ture (sauf mention spciale).
Jy ai galement inclus les oprateurs ajouts par le C++
afn de tous les runir en un seul endroit.
Oprateurs par ordre de priorit
0pcraIcur SgncaIon
Groupe 1 (pas dassociativit)
:: Oprateur de rsolution de port (C++)
Groupe 2
() Modifcation de la priorit des oprateurs
ou appel de fonction
[] lment dun tableau
. Champ de structure ou dunion
(ou de fonction membre en C++)
-> Champ dsign par pointeur (slection de
membre par drfrencement)
++ Incrmentation (post-fxe, par exemple ++i)
-- Dcrmentation (post-fxe, par exemple --i)
type() Transtypage explicite (C++)
new Cration dynamique dobjets (C++)
new[] Cration dynamique de tableaux (C++)
delete Destruction des objets crs dynamiquement (C++)
delete[] Destruction des tableaux crs
dynamiquement (C++)
0pcraIcurs cI prorIc (L cI L++)
20 LhAPIJL 1 8ascs hcrIccs du |angagc L
Oprateurs par ordre de priorit (suite)
0pcraIcur SgncaIon
Groupe 3 (associativit de droite gauche)
! Ngation boolenne
~ Complment binaire
+ Plus unaire
- Oppos (appel aussi moins unaire)
++ Incrmentation (prfxe, par exemple i++)
-- Dcrmentation (prfxe, par exemple i--)
& Adresse (pas le et binaire)
* Accs aux donnes indiques par un pointeur
(drfrencement)
sizeof() Taille en nombre doctets de lexpression
typeid() Identifcation dun type (C++),
pas toujours implment
(type) Transtypage (cast)
const_cast Transtypage de constante (C++)
dynamic_cast Transtypage dynamique (C++)
reinterpret_cast Rinterprtation (C++)
static_cast Transtypage statique (C++)
Groupe 4
.* Slection de membre par pointeur
sur membre (C++)
->* Slection de membre par pointeur sur membre
par drfrencement
21
Oprateurs par ordre de priorit (suite)
0pcraIcur SgncaIon
Groupe 5
* Multiplication
/ Division
% Modulo (reste de la division euclidienne)
Groupe 6
+ Addition
- Soustraction
Groupe 7
<< Dcalage gauche
>> Dcalage droite
Groupe 8
< Test strictement infrieur
<= Test infrieur ou gal
> Test suprieur
>= Test suprieur ou gal
Groupe 9
== Test gal
!= Test diffrent de
Groupe 10
& ET binaire
Groupe 11
^ OU eXclusif (XOR) binaire
0pcraIcurs cI prorIc (L cI L++)
22 LhAPIJL 1 8ascs hcrIccs du |angagc L
Oprateurs par ordre de priorit (suite)
0pcraIcur SgncaIon
Groupe 12
|
OU binaire
Groupe 13
&& ET logique (ou boolen)
Groupe 14
||
OU logique (ou boolen)
Groupe 15
? : Oprateur conditionnel
Groupe 16 (associativit de droite gauche)
= Affectation
+= Incrmentation et affectation
-= Dcrmentation et affectation
*= Multiplication et affectation
/= Division et affectation
%= Modulo et affectation
<<= Dcalage gauche et affectation
>>= Dcalage droite et affectation
&= ET binaire et affectation
|
= OU binaire et affectation
^= XOR binaire (OU exclusif) et affectation
Groupe 17
, (virgule) Sparateur dans une liste dexpressions
2
8ascs du
|angagc L++
Le C++ est un langage de programmation permettant la
programmation sous de multiples paradigmes, comme par
exemple la programmation procdurale (hrite du langa-
ge C), la programmation oriente objet (voir le Chapitre 4)
et la programmation gnrique (voir le Chapitre 5).
Depuis 1995 environ, C++ est le langage le plus utilis au
monde.
Avant daborder des notions plus complexes, ce chapitre se
concentre sur les bases du C++, en plus de celles hrites
du langage C.
Hello world en C++
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << Hello world ! << std::endl;
return 0;
}
24 LhAPIJL 2 8ascs du |angagc L++
Voici le pendant C++ du traditionnel HelloWorld du lan-
gage C, que nous avons vu dans le chapitre prcdent.
Notez que par habitude, lextension du fchier nest plus
.c mais .cpp (on rencontre aussi .cxx ou encore
.C surtout sous Unix et GNU-Linux, qui distinguent
minuscules et majuscules dans les noms de fchiers). Pour les
fchiers den-ttes C++, la STL (bibliothque standard du
C++) a simplement supprim lextension (plus de .h ) ;
mais aujourdhui, lextension standard est .hpp (que
lon retrouve dans la bibliothque BOOST).
Si vous avez russi compiler ce programme en C, vous y
parviendrez sans diffcult en C++. Par contre, il ne faut
plus invoquer gcc mais g++.
Les mots-cls
Voici la liste des mots rservs du C++ qui ne sont pas
dj prsents dans le langage C. Elle vous sera utile pour
retrouver facilement la section associe.
Les mots-cls du C++
MoI-c|c Pagc MoI-c|c Pagc
bool 29 inline 46
catch 123 mutable 72
class 62 namespace 40
const_cast 34 new 113
delete 113 operator 37
dynamic_cast 36 private 75
explicit 71 protected 75
false 29 public 75
friend 66 reinterpret_cast 35
25
Les mots-cls du C++ (suite)
MoI-c|c Pagc MoI-c|c Pagc
static_cast 33 typeid 86
template 96 typename 101
this 67 using 41
throw 123 virtual 79
true 29 wchar_t 31
try 123
Les constantes
Une constante est une valeur qui ne change pas au cours
de lexcution dun programme.
Une constante ressemble une macro par diffrents
aspects :
sa porte est rduite au fchier o elle est dclare ;
les expressions lutilisant sont values la compila-
tion ;
elle peut tre utilise pour dfnir la taille dun tableau
de type C.
Toutefois, contrairement aux macros, le compilateur peut
allouer un emplacement mmoire o stocker la constante
lorsque cela est requis. Cest par exemple le cas lorsque
lon utilise son adresse :
const int constante_entiere = 345;
const int *ptr_sur_constante = &constante_entiere;
Si les macros C #defne sont toujours disponibles, il est pr-
frable dutiliser le concept de constantes quoffre le C++.
Cela permet une vrifcation de type la compilation et
diminue le risque derreur.
Lcs consIanIcs
28 LhAPIJL 2 8ascs du |angagc L++
const int a = 2;
int const b = 7; // quivalent la ligne prcdente
const Objet unobjet; // un objet peut tre une constante
const int const c = 7; // ERREUR : const dupliqu
const double d; // ERREUR : initialisation manquante
Pour les pointeurs, le qualifcatif const peut aussi bien
sappliquer au pointeur qu llment point :
const int entier1;
int* ptr = &entier1; // ERREUR : conversion invalide

// Pointeur sur une constante
const int *a = &constante_entiere;
int const *b = &constante_entiere; // quivalent
// la ligne prcdente
a = &constante_entiere;
*a = 4; // ERREUR : on ne modife pas une constante

// Pointeur constant sur une variable
int *const c = &entier;
int *const c; // ERREUR : initialisation manquante
c = &entier1; // ERREUR : on ne modife pas une constante
*c = 5;

// Pointeur constant sur une constante
const int *const d = &constante_entiere;
int const *const e = &constante_entiere; // quivalent
// la ligne prcdente
const int *const f; // ERREUR : initialisation manquante
d = &entier1; // ERREUR : on ne modife pas une constante
*d = 5; // ERREUR : on ne modife pas une constante
21
Dclarations de variables
En C++, la dclaration de variables est considre comme
une instruction. Il nest pas ncessaire de regrouper toutes
les dclarations de variables en dbut de bloc comme
en C.
int a; // dclaration dune variable
int b = 0; // dclaration et initialisation
Objet o; // dclaration et appel du constructeur
AIIcnIon
La dclaration de variables peut entraner lexcution de beau-
coup de code, notamment lors de linitialisation des objets
(classes).
Une variable dclare dans une boucle for implique que
sa porte reste limite cette dernire :
for (int i=0 ; i<n ; ++i)
//
for (int i=k ; i>=0 ; --k)
//
AIIcnIon
Certains vieux compilateurs C++, comme Visual C++ 6, ne
grent pas cette spcifcit et transforment toute dclaration
normalement locale la boucle for en une dclaration prcdant
celle-ci. Ainsi, le code ci-dessus ne compilerait pas avec un tel
compilateur : un message derreur prtextant que la variable i
est dj dclare serait gnr pour la deuxime boucle.
0cc|araIons dc varah|cs
28 LhAPIJL 2 8ascs du |angagc L++
Pour vous assurer quune variable a une porte limite
un fchier, utilisez un espace de nom anonyme plutt que
de recourir au mot-cl static :
static int n; // correcte mais de style C
namespace // on prfrera le style C++
{
int n;
}
Lutilisation de static pour une dclaration de variable
dans un bloc a le mme effet quen C : linitialisation na
lieu quune fois et son comportement est semblable celui
dune variable globale uniquement visible dans ce bloc.
int f(int x)
{
static int a = x;
return a;
}
int main(void)
{
cout << f(10) << endl ;
cout << f(12) << endl ;
}
Produira la sortie suivante :
10
10
20
Les nouveaux types de variables
du C++
bool
Le type bool accepte deux tats :
true (vrai) : correspond la valeur 1 ;
false (faux) : correspond la valeur 0.
Ce type est cod sur le mme nombre de bits que le type
int. Lorsque lon convertit un type numraire en bool,
toute valeur non nulle est considre comme true.
bool vrai = true;
bool faux = false;
Les rfrences
Une rfrence est une sorte de pointeur masqu. Pour
dclarer un pointeur, il sufft de rajouter un et commercial
(&) aprs le type : si T est un type, le type rfrence sur T
est T&.
int a = 3;
int& r = a ; // r est une rfrence sur a
Il est obligatoire dinitialiser une rfrence lors de sa dcla-
ration, sinon vous obtiendrez un message derreur. En
effet, r = b; ne transformera pas r en une rfrence sur b
mais copiera la valeur de b dans r.
Lcs nouvcaux Iypcs dc varah|cs du L++
80 LhAPIJL 2 8ascs du |angagc L++
AsIucc
Les rfrences permettent de dfnir des raccourcis (ou alias)
sur des objets.
int& element = tableau[indice];
element = entier;
est quivalent :
tableau[indice] = entier;

AIIcnIon
Une fonction ne doit jamais renvoyer une rfrence sur un
objet qui lui est local.
int& fonction()
{
int res;
//
return res; // retourne une rfrence sur un objet
// qui sera aussitt dtruit !
}
De la mme manire, il faut se mfer. Dans certains cas, une
rfrence retourne par une fonction peut savrer peu stable.
class Pile
{
//
public:
double& sommet() const { return m_valeurs[m_niveau_

courant 1] ; }
double depiler() { return m_valeurs[--m_niveau_

courant] ; }
};
Pile pile;
//
pile.sommet() = pile.depiler() + 10.0; // Le rsultat
est imprvisible !

81
enum, struct et union
enum MonType { mtValeur1, mtValeur2, mtValeur3 };
MonType uneInstance = mtValeur2;
struct MaStructure { /* */ };
MaStructure a;
union MonUnion { /* */ };
MonUnion u;
Dj connu en C, la dclaration dun enum, dune struct
ou dune union se trouve simplife en C++. En effet, il
ny a plus besoin de rpter le mot-cl lors dune instan-
ciation ; lidentifant choisi lors de la dclaration sufft.
Nous ne dtaillerons pas ici la syntaxe de leur contenu, qui
reste quivalente au langage C.
Info
Cest un peu comme si en C, toute dclaration tait automati-
quement suivie de :
typedef enum MonType MonType;
Il convient par l de faire attention au masquage local de toute
autre dclaration de niveau suprieur.
wchar_t
wchat_t est le type utilis pour les jeux de caractres tendus
tel Unicode. Contrairement au C ou ce type est dfni par
un typedef (via linclusion du fchier den-tte <stddef.h>),
en C++ wchar_t est bel et bien un mot-cl du langage.
Lcs nouvcaux Iypcs dc varah|cs du L++
82 LhAPIJL 2 8ascs du |angagc L++
Conversion de type C
lorigine, le comit de standardisation C++ prvoyait de
supprimer la conversion de type C. Cette dernire na t
conserve que par soucis de rutilisation de code ancien et
de compatibilit (un compilateur C++ doit pouvoir com-
piler du C). Cest pourquoi tout programmeur C++ est
encourag la bannir et plutt utiliser les nouveaux op-
rateurs de conversion.
Pourquoi les conversions de type C sont-elles maintenant
considres comme obsoltes ? Voyez plutt :
void *p = &x;
int n = (int) p; // conversion de type C
Cette conversion de type C, inoffensive de premier abord,
recle en fait plusieurs dangers. Premirement, elle effectue
des oprations diffrentes selon le contexte. Par exemple,
elle peut transformer de manire sre un int en double, mais
elle peut aussi effectuer des oprations intrinsquement dan-
gereuses comme la conversion dun void* en valeur num-
rique (voir lexemple ci-dessus). En relisant un code source
contenant une telle conversion, un programmeur ne pourra
pas toujours dterminer si celle-ci est sre ou non, si le
programmeur dorigine a fait une erreur ou non.
Pire, une conversion de type C peut effectuer plusieurs
oprations en une. Dans lexemple suivant, non seulement
un char* est converti en unsigned char*, mais en plus le
qualifcateur const est limin en mme temps :
const char *msg = une chaine constante;
unsigned char *ptr = (unsigned char*) msg;

// est-ce intentionnel ?
Encore une fois, il est impossible de dire si cest la volont
du programmeur dorigine ou un oubli. Ces problmes
88
relatifs ce type de conversion sont connus depuis des
annes. C++ offre une meilleure solution avec les opra-
teurs de conversion. Ils rendent explicite lintention du
programmeur et prservent la capacit du compilateur
signaler les bogues potentiels prcits.
Conversion avec static_cast
static_cast<type>(expression)
Cest la conversion la plus proche de lancienne conversion C.
Elle reste ventuellement dangereuse, mais rend explicite lin
tention du programmeur. Sont principalement autorises, en
plus des conversions standard, les conversions :
dun type entier vers un type numration ;
de B* vers D*, o B est une classe de base accessible de D
(la rciproque est une conversion standard).
Elle peut tre utilise mme lorsquune conversion impli-
cite existe :
bool b = true;
int n = static_cast<int>(b);
Dans dautres cas, lutilisation de static_cast est obliga-
toire, par exemple lors de la conversion partir dun
void* :
int n = 0;
void *ptr = &n;
int *i = static_cast<int*>(ptr); // obligatoire
static_cast utilise linformation disponible la compila-
tion pour effectuer la conversion de type requise. Ainsi, la
Lonvcrson avcc static_cast
84 LhAPIJL 2 8ascs du |angagc L++
source et la destination peuvent ne pas avoir la mme
reprsentation binaire, comme lors de la conversion dun
double vers un int o loprateur de conversion effectue le
travail ncessaire une conversion correcte.
Utiliser static_cast permet dviter certains cueils
comme :
const char *msg = une chaine constante;
unsigned char *ptr = static_cast<unsigned char*>( msg);

// erreur
Cette fois, le compilateur signale une erreur indiquant
quil est impossible denlever le qualifcateur const avec ce
type de conversion. Il en est de mme avec le qualifcateur
volatile.
Conversion avec const_cast
const_cast<type>(expression)
Enlever ou ajouter une qualifcation const ou volatile
requiert loprateur de conversion const_cast. Notez que
le type et le type de lexpression doivent tre les mmes,
aux qualifcatifs const et volatile prs, sinon le compila-
teur gnrera un message derreur.
struct A
{
void fonction(); // fonction membre non const
};
void ma_fonction(const A& a)
{
a.func(); // erreur : appel une fonction non const
De manire vidente, il sagit dune erreur de conception.
La fonction fonction() aurait d tre dclare const.
85
Nanmoins, un tel code existe parfois dans des biblioth-
ques existantes mal conues. Un programmeur inexpri-
ment sera tent dutiliser une conversion brute la C.
Pour rgler un tel problme, il est prfrable de supprimer
le qualifcateur const ainsi :
A &ref = const_cast<A&>(a) ; // enlve const
ref.fonction(); // fonctionne maintenant correctement
AIIcnIon
Souvenez-vous toutefois que si const_cast permet de suppri-
mer le qualifcateur const, vous ne devez pas pour autant vous
autoriser modifer lobjet. Sinon, attendez-vous de mauvai-
ses surprises
Conversion avec reinterpret_cast
reinterpret_cast<type>(expression)
loppos de static_cast, reinterpret_cast effectue une
opration relativement dangereuse ou non portable. rein-
terpret_cast ne change pas la reprsentation binaire de
lobjet source. Toutefois, il est souvent utilis dans des appli-
cations bas niveau qui convertissent des objets en dautres
donnes transmises un fux doctets (et vice versa). Dans
lexemple suivant, reinterpret_cast est utilis pour tromper
le compilateur, permettant au programmeur dexaminer les
octets lintrieur dune variable de type foat :
foat f=123;
unsigned char *ptr = reinterpret_cast<unsigned char*>(&f);
for (int i=0 ; i<4 ; ++i)
cout << ptr[i] << endl;
Lonvcrson avcc reinterpret_cast
88 LhAPIJL 2 8ascs du |angagc L++
Utilisez loprateur reinterpret_cast pour expliciter toute
conversion potentiellement dangereuse (et probablement
non portable).
Info
En quoi lexemple ci-dessus peut-il tre non portable ? Imaginez
une sauvegarde/lecture fchier dun foat ou dun int avec un
tel code. Sauvez votre valeur sur une machine little endian
puis rechargez le fchier de sauvegarde sur une machine de
type big endian. Vous ne retrouverez probablement pas la
valeur dorigine
Conversion avec dynamic_cast
dynamic_cast<type>(expression)
dynamic_cast diffre des trois autres oprateurs. Il utilise les
informations de type dun objet pendant lexcution du
programme plutt que celles connues la compilation
(pour plus dinformation ce sujet, voir la section
Obtenir des informations de type dynamiquement du
Chapitre 4). Deux scnarios requirent lutilisation de
dynamic_cast :
la conversion de spcialisation (ou downcast) lors de la
conversion dune rfrence ou dun pointeur de classe
vers une rfrence ou un pointeur dune classe drivant
de la classe que lon veut downcaster ;
la conversion transversale (ou crosscast) lors de la conver-
sion dun objet dhritage multiple vers une de ses clas-
ses de base.
81
Surcharge
La surcharge de fonctions (les oprateurs sont des fonctions)
est une nouveaut apporte par le C++. Ce mcanisme,
apparemment fort simple, suit des rgles strictes dont le
rsultat nest pas toujours intuitif. Mais avant daller plus
loin, voici ce mcanisme :
reprer les fonctions candidates ;
les fltrer en ne gardant que les viables ;
les fltrer de nouveau selon le critre de la meilleure
fonction viable.
la suite de ce mcanisme, sil reste plus dune fonction,
on aboutit une erreur de compilation du type appel
ambigu ; si la fonction trouve est inaccessible (comme
une fonction membre prive ou protge) ou est virtuelle
pure, on aboutit galement une erreur.
Info
Les signatures des fonctions ne tiennent pas compte du type
de la valeur de retour. Par consquent, le mcanisme de sur-
charge ne peut pas en tenir compte non plus.
Les fonctions candidates :
ont le mme nom que la fonction appele ;
appartiennent toutes la mme rgion dclarative (la
recherche commence dans le mme niveau que lappel,
puis remonte au niveau suprieur jusqu en trouver
une, puis recense toutes celles de ce mme niveau).
Surchargc
88 LhAPIJL 2 8ascs du |angagc L++
Lexemple suivant illustre ce principe.
void print(double);
void affcher()
{
void print(int);
print(1.2); // fonctions candidates : print(int)
}

class Reel
{
public:
void print(double);
};

class Entier : public Reel
{
public:
void print(int);
};
Entier e;
e.print(1.2); // fonctions candidates :

Entier::print(int)
AIIcnIon
Une exception est faite pour les oprateurs o lensemble des
fonctions candidates stend lunion de ces trois domaines de
recherche :
les fonctions membres candidates (si le premier oprande
est un objet) ;
les fonctions non membres candidates ;
les oprateurs redfnis.
Une fonction candidate est viable si :
elle possde autant de paramtres que lappel (en tenant
compte des valeurs par dfaut) ;
le type de chaque paramtre correspond ( une conver-
sion implicite prs).
80
Info
Les fonctions membres sont traites comme des fonctions
standard en leur adjoignant comme premier paramtre lobjet
du type de la classe. Par exemple :
class MaClasse
{
void fonction_1(int);
void fonction_2(double) const;
};
sera vu comme :
void fonction_1(MaClasse*, int);
void fonction_2(const MaClasse*, double);
et lappel :
monObject.fonction_1(3);
comme :
fonction_1(&monObjet,3);

La meilleure fonction viable est dtermine en fonction
de la qualit des conversions utilises pour dterminer sa
viabilit. Une conversion est meilleure si (dans lordre) :
elle ne ncessite aucune conversion, ou est une conver-
sion triviale comme Type[] vers Type* (et sa rcipro-
que), Type vers const Type (uniquement dans ce sens),
f() vers (*f)() (et sa rciproque) ;
elle est une promotion de char vers int, short vers int
ou foat vers double ;
elle est une conversion standard (par exemple int vers
foat) ;
elle est une conversion utilisateur.
Surchargc
40 LhAPIJL 2 8ascs du |angagc L++
void f(int, double);
void f(double, int);
f(1, 1); // appel ambigu
f(1.0, 1.0); // appel ambigu
Exemple de rsolution de surcharge ambigu
AIIcnIon
Nous avons dit que la rsolution pouvait parfois tre drou-
tante. En voici un exemple :
class Object
{
public:
operator int();
};
void fonction(double, int);
void fonction(int, Objet);
Objet obj;
fonction(0.99, obj);
Dans ce cas, la meilleure fonction viable sera fonction(int,Obj)
malgr la prsence de loprateur de conversion.
Les espaces de noms
namespace nom
{
// dclarations / implmentations
}
Les espaces de noms permettent de ranger du code dans des
botes virtuelles. Cela permet par exemple de faire cohabiter
41
des fonctions ayant le mme nom et les mmes types de
paramtres. Le mme principe est applicable aux dfni-
tions de classes et aux variables.
Si vous disposez de deux (ou plus) entits (donnes ou
mthodes) de mme nom, en C standard seule la plus
locale est accessible. C++ permet de prciser de quel nom
il est question grce la syntaxe o::nom (::nom signife que
lon dsire accder lespace global).
namespace perso
{
void f();
}
void f();
Tout ce qui est dfni dans perso (donc entre les accolades)
est diffrent de ce qui est dfni ailleurs. lextrieur de
perso, on peut nanmoins accder sa fonction f() grce
au code perso::f().
Il est possible dutiliser une prfrence dappel grce la
dclaration using. Ainsi, dans notre exemple prcdent,
using perso; permet daccder toutes les composantes de
perso (dans la porte de la dclaration, videmment).
Utilisez-la au niveau global et vous obtiendrez une prf-
rence par dfaut pour le code qui la suit. Utilisez-la dans
un bloc et la prfrence sera locale au bloc.
Info
Vous pouvez imbriquer les espaces de noms, mais vous ne
pouvez pas en crer dans une classe ou un bloc de code (cest-
-dire dans le corps dune fonction).
Lcs cspaccs dc noms
42 LhAPIJL 2 8ascs du |angagc L++
AsIucc
Utilisez les espaces de noms anonymes pour limiter la porte
de vos dclarations plutt que de les dclarer static. Par
exemple :
namespace A
{
namespace // anonyme car pas de nom
{
void fonction()
{
//
}
}
fonction(); // OK : visible
}
fonction(); // ERREUR : nest plus visible
La fonction() est visible dans la porte du namespace ano-
nyme.
Incompatibilits avec le C
Pointeurs de type void (C90 et C99)
En C, il est possible de raliser une conversion implicite
dun type donn vers un pointeur gnrique de type void*,
et vice versa.
void *ptr_void;
int *ptr_int;
//
ptr_void = ptr_int;
ptr_int = ptr_void; // en C++ : gnre un message derreur
48
En C++, la conversion dun pointeur gnrique void*
vers un pointeur dun type donn doit tre explicite de
la manire suivante (voir la section Conversion avec
reinterpret_cast ) :
ptr_int = reinterpret_cast<int*>(ptr_void);
Instruction goto (C90 et C99)
int i = 0;
goto start:
int j = 1; // ERREUR en C++
//
start:
//
En C++, linstruction goto ne peut pas tre utilise pour
sauter une dclaration comportant une initialisation, sauf
si le bloc qui contient cette dclaration est entirement
saut.
Type de caractres et surcharge (C90 et C99)
Les types utiliss pour reprsenter les caractres ne sont pas
les mmes en C et en C++. Le C utilise un entier (int)
alors que le C++ utilise le type caractre (char). Cela peut
avoir son importance si vous surchargez des fonctions
(notamment de la bibliothque C standard), comme dans
cet exemple :
int putchar(int c); // prsent dans <stdio.h>
int putchar(char c) // ma surcharge
{
printf(%c\n, c);
}
IncompaIh|Ics avcc |c L
44 LhAPIJL 2 8ascs du |angagc L++
Dans ce cas, le code putchar(a); appellera la seconde
fonction et non la premire.
Initialisation de tableaux de caractres
char tableau[5] = 12345;
En C, il est possible dinitialiser un tableau de caractres
avec une chane ayant la mme longueur, sans compter
son zro (\0) terminal. En C++, une telle initialisation
gnrera un message derreur.
Type de retour des fonctions
fonction();
En C, omettre le type de retour dune fonction lors de sa
dclaration quivaut implicitement un retour de type
int. Ceci nest pas permis en C++.
Type boolen
typedef int bool;
En C, il tait possible de dfnir un type bool. En C++, ce
nest pas permis et gnre un message derreur du type :
error: redeclaration of C++ built-in type bool .
Lier du code C et C++
extern C
Pour grer la surcharge de fonctions (voir la section
Surcharge ), le compilateur gnre un symbole de noms
45
plus long que celui de la fonction elle-mme. Ce procd,
appel name mangling, adjoint au nom de la fonction des
informations permettant de connatre le nombre et le type
de ses arguments. Cest ce nom long quutilise lditeur de
liens.
Les compilateurs C ne disposent pas de ce mcanisme de
signature des fonctions. Et pour cause : il ny a pas de sur-
charge en C. Du coup, il est ncessaire dencadrer toutes
les fonctions C ainsi :
extern C
{
// dclarations de variables et fonctions C
}
Vous pouvez galement faire prcder chaque dclaration
par cette mme mention :
extern C void fonctionC(int);
extern C double autreFonction(double);
AsIucc
Nhsitez pas dans vos fchiers den-ttes C utiliser la macro
__cplusplus qui nest prdfnie quen C++. Vous rendrez
ainsi ceux-ci portables.
#ifdef __cpluplus
extern C {
#endif
// vos dclarations C
#if __cpluplus
}
#endif

Lcr du codc L cI L++
48 LhAPIJL 2 8ascs du |angagc L++
Embarquer une fonction
inline Type fonction(...) { ... }
Le langage C++ introduit le concept de fonctions embar-
ques en ajoutant le mot-cl inline, qui permet de dfnir
des fonctions dont lappel dans le programme sera rem-
plac par le code de la fonction elle-mme. Elles doivent
tre rserves de prfrence aux petites fonctions (mem-
bres de classe ou globales) frquemment utilises.
inline int doubler(int i)
{
return 2 * i;
}
AIIcnIon
Ce mot-cl est une indication donne au compilateur. Il ne
garantit pas que le code sera effectivement embarqu.
Constantes usuelles
#include <limits>
#include <climits>
#include <cfoat>
Vous trouverez toutes les constantes usuelles dans ces trois
fchiers den-tte. Lexemple suivant montre comment
connatre la valeur maximale du type double ; il utilise
<limits> :
std::numeric_limits<double>::max();
3
PonIcurs cI
rcfcrcnccs
Un pointeur est simplement une variable contenant une
adresse mmoire, indiquant o commence le stockage
mmoire dune donne dun certain type. Une rfrence est
un pointeur masqu, permettant de manipuler lobjet
point par un pointeur comme sil sagissait dune
variable ordinaire.
Les pointeurs sont couramment utiliss en C et C++.
AIIcnIon
Il est essentiel de bien comprendre les pointeurs et les rfren-
ces. Une erreur de manipulation est vite arrive. Gardez en tte
que la mmoire dun ordinateur nest quune suite ordonne
de 0 et de 1, groups par blocs. Historiquement, il sagissait de
bloc de 8 bits, cest--dire un octet. Ces blocs sont implicite-
ment numrots. Le numro dun bloc correspond son adresse.
Larchitecture des ordinateurs ayant volu, certaines donnes
doivent dbuter des adresses multiples de 4 (sur une archi-
tecture 32 bits) ou de 8 (sur une architecture 64 bits). Cest ce
que lon appelle lalignement .
Pour en savoir plus sur les problmes dalignement mmoire,
vous pouvez vous rfrer la page web hIIp:jjfr.wkpcda.orgj
wkjA|gncmcnI_dc_donnccs.
48 LhAPIJL 8 PonIcurs cI rcfcrcnccs
45
461
23443
i
j
pil
23444
23443
23442
23441
23440
23439
2
1
0
Adresses Mmoire
Adresses croissantes
Variables
Figure 3.1 : Notions de pointeur et dadresse
Crer et initialiser un pointeur
Type* pointeur; *a
Pour connatre ladresse dune variable, on utilise une indi
rection avec loprateur &. Lorsque lon veut accder au
contenu dune variable pointe, on utilise un drfrence
ment avec loprateur *.
Le code suivant illustre ces manipulations :
int a; // dclaration dune variable, ici de type entier
int *pa; // dclaration dun pointeur sur entier
pa = &i; // indirection : on rcupre ladresse de a
*pa = 0; // drfrencement : on utilise la variable
// prcdemment drfrence
*pa = *pa + 1; // encore : ici pour ajouter 1 au contenu
// de la variable pointe (autrement dit a)
40
AIIcnIon
Le * dans la dclaration dun pointeur ne se rapporte qu la
variable immdiatement sa droite. Ainsi :
int *a, b;
dclare a comme pointeur sur un entier MAIS b comme un
entier et NON un pointeur sur entier. Pour que a et b soient
tous deux des pointeurs, il faut rpter le * devant chaque
nom de variable (du moins celles que nous souhaitons tre des
pointeurs), comme suit :
int *a, *b;

Accder aux donnes
ou fonctions membres
pointeur->membre
pointeur->fonction()
(*pointeur)->membre
(*pointeur)->fonction()
Lorsque lon utilise des pointeurs sur des structures ou des
classes, accder aux donnes ou fonctions membres se ra-
lise de deux faons :
struct Copain
{
int m_age;
};
Copain toto;
Copain *pCopain = &toto;
(*pCopain).age = 5; // 1re faon
pCopain->age = 7; // 2e faon, plus pratique
Acccdcr aux donnccs ou foncIons mcmhrcs
50 LhAPIJL 8 PonIcurs cI rcfcrcnccs
Info
Historiquement, la bibliothque standard du langage C avait
introduit la constante NULL (par lintermdiaire dune macro).
La valeur de cette dernire, bien que souvent 0, pouvait valoir
nimporte quelle valeur (certains compilateurs la dfnissaient
1). Le C++ a unif cette valeur 0, facilitant ainsi le por-
tage des programmes.
Certains encouragent lutilisation systmatique de 0, dautres
celle de la macro NULL quitte la dfnir soi-mme 0 si elle
nexiste pas. Rjouissez-vous, la future norme C++0x (voir
lannexe qui lui est consacre) rconciliera certainement tout
le monde en introduisant le nouveau mot-cl nullptr.
Crer et utiliser une rfrence
Type& reference;
Les rfrences, ajoutes par le C++, masquent le systme
dindirection et de drfrencement des pointeurs.
Lexemple suivant montre quel point leur utilisation est
simple :
int I;
int &rI = I; // rfrence sur la variable I
rI = rI + 1; // ajoute 1 rI et donc aussi a I
Dclarer un pointeur sur un tableau
type (*tableau)[N];
Ce code dclare un pointeur sur un tableau de N lments.
AIIcnIon
type* tableau[N];
dclare un tableau de N pointeurs.
51
Pointeurs et tableaux
Diffrence de type
Du point de vue du compilateur, il existe une diff-
rence entre :
T var[] qui dfnit une variable de type tableau de
type T et ;
T* var qui dfnit une variable de type pointeur sur
type T.
Ainsi, si vous dfnissez par exemple char a[6] dans un
fchier source, pour le rendre public et accessible par
dautres fchiers sources, vous devez le dclarer (par
exemple dans un fchier den-tte) comme extern
char a[6] ou extern char a[] et non extern char *a.
Diffrence mmoire
On entend souvent dire que T a[] et T* a sont qui-
valents. Cela est vrai lors de leur passage en tant que
paramtre de fonction. Cela est faux vis--vis de la
structure mmoire lors de la dclaration.
Un exemple valant mieux que mille mots, consid-
rons les deux dclarations suivantes :
char a[] = bonjour;
char *p = le monde;
Les donnes correspondantes en mmoire peuvent
tre reprsentes ainsi :
+---+---+---+---+---+---+---+----+
a :
|
b
|
o
|
n
|
j
|
o
|
u
|
r
|
\0
|

+---+---+---+---+---+---+---+----+
+-----+ +---+---+---+---+---+---+---+---+----+
p :
|
*=====>
|
l
|
e
|

|
m
|
o
|
n
|
d
|
e
|
\0
|

+-----+ +---+---+---+---+---+---+---+---+----+
PonIcurs cI Iah|caux
52 LhAPIJL 8 PonIcurs cI rcfcrcnccs
Il est important de raliser cette diffrence pour com-
prendre que le code gnr par la suite peut infuer sur
les performances. En effet, dans le deuxime cas une
opration sur larithmtique des pointeurs se cache der-
rire linstruction p[3].
quivalence lors de laccs
Mme sil existe une diffrence subtile entre tableau C
et pointeur, tout accs un lment de tableau a un
quivalent avec un appel par pointeur.
Par exemple int t[5]; rserve 5 entiers conscutifs en
mmoire, et t correspond un pointeur sur le dbut
de cette mmoire. Ainsi, si int* pi = t; alors *(pi+3)
ou pi[3] est quivalent t[3].
Pour les tableaux multidimensionnels, les choses sont
un peu plus complexes. Tout dabord, il faut compren-
dre comment un tableau multidimensionnel est orga-
nis en mmoire. Prenons le cas dun tableau deux
dimensions. Par exemple T mat[4][3] peut tre repr-
sent ainsi :
+-----+-----+-----+-----+-- ---+-----+
mat ==
|
a00
|
a01
|
a02
|
a11
|

|
a32
|

+-----+-----+-----+-----+-- ---
|
-----+
+-----+-----+-----+
mat == mat[0] --->
|
a00
|
a01
|
a02
|

+-----+-----+-----+
mat[1] --->
|
a10
|
a11
|
a12
|

+-----+-----+-----+
mat[2] --->
|
a20
|
a21
|
a22
|

+-----+-----+-----+
mat[3] --->
|
a30
|
a31
|
a32
|

+-----+-----+-----+
58
Le tableau dlments est stock en mmoire ligne
aprs ligne ; pour un tableau de taille m n dlments
de type T, ladresse de llment (i,j) peut sobtenir
ainsi :
adresse(mat[i][j]) == adresse(mat[0][0]) + (i*n +j) * size(T)
adresse(mat[i][j]) == adresse(mat[0][0]) +
i * n * size(T) +
j * size(T)
adresse(mat[i][j]) == adresse(mat[0][0]) +
i * size(une ligne de T) +
j * size(T)
Dune manire gnrale si on a T tableau[D0][D1][D2]
[DN], on peut accder llment tableau[i0][i1][i2]
[iN] par la formule suivante :
*(tableau + i0 + D1* (i1 + (D2* (i2 + D3* ( + DN*iN))))
Cette formule omet la taille dun lment car le com-
pilateur la dduit automatiquement en fonction du
type du pointeur. Du coup, prenez garde au fait que si
le type de pointeur est diffrent, ladresse obtenue nest
pas la mme. Si lon a :
int *pi = 0;
char* pc = 0;
alors (pi + 1) != (pc + 1).
quivalence en tant que paramtre
Lors du passage dun tableau une fonction, seul le
pointeur sur le dbut du tableau est transmis. Du coup,
on a une quivalence stricte entre les deux reprsenta-
tions. Par contre, sil sagit dun tableau multidimen-
sionnel, on a tout intrt garder la dclaration sous
forme de tableau pour viter de se tromper dans le
calcul de la conversion des indices.
PonIcurs cI Iah|caux
54 LhAPIJL 8 PonIcurs cI rcfcrcnccs
Dclarer un pointeur
sur une fonction
Type (*pointeur_sur_fonction)(paramtres);
typedef Type (*type_pointeur_sur_
fonction)(paramtres);
type_pointeur_sur_fonction pointeur_sur_fonction;
Les parenthses autour de *pointeur_sur_fonction sont
obligatoires, sinon le compilateur pensera quil sagit de la
dclaration dune fonction renvoyant un pointeur sur le
Type donn. Lexemple suivant montre comment utiliser
les pointeurs sur fonction et donne un aperu de leur int-
rt. Cet exemple est crit en C, mais fonctionne parfaite-
ment en C++.
#include <stdio.h>
#include <string.h>

#defne MAX_BUF 256

long arr[10] = { 3,6,1,2,3,8,4,1,7,2};
char arr2[5][20] = { Mickey Mouse,
Donald Duck,
Minnie Mouse,
Goofy,
Ted Jensen };

// Dclaration du type de la fonction de comparaison
// utilis par le tri bulle
typedef int (*FnComparaison)(const void *, const void *);
// Fonction de tri bulle gnrique
void tri_bulle(void *p, int width, int N, FnComparaison fptr);
55
// Deux fonctions de comparaison
int compare_chaine_c(const void *m, const void *n);
int compare_long(const void *m, const void *n);

int main(void)
{
int i;
puts(\nAvant le tri :\n);

for (i = 0; i < 10; i++) // Affche les ints de arr
printf(%ld ,arr[i]);
puts(\n);

for (i = 0; i < 5; i++) // Affche les chanes de arr2
printf(%s\n, arr2[i]);

tri_bulle(arr, 4, 10, compare_long); // Trie les longs
tri_bulle(arr2, 20,5, compare_chaine_c); // Trie les chanes
puts(\n\nAprs le tri :\n);

for (i = 0; i < 10; i++) // Affche les longs tris
printf(%d ,arr[i]);
puts(\n);

for (i = 0; i < 5; i++) // Affche les chanes tries
printf(%s\n, arr2[i]);
return 0;
}

// Implmentation de la fonction de tri bulle gnrique
void tri_bulle(void *p, int width, int N,
FnComparaison fptr)
{
int i, j, k;
unsigned char buf[MAX_BUF];
unsigned char *bp = (unsigned char*)p;

for (i = N-1; i >= 0; i--)
0cc|arcr un ponIcur sur unc foncIon
58 LhAPIJL 8 PonIcurs cI rcfcrcnccs
{
for (j = 1; j <= i; j++)
{
k = fptr((void *)(bp + width*(j-1)),
(void *)(bp + j*width));
if (k > 0)
{
memcpy(buf, bp + width*(j-1), width);
memcpy(bp+width*(j-1), bp+j*width, width);
memcpy(bp+j*width, buf, width);
}
}
}
}

int compare_chaine_c(const void *m, const void *n)
{
char *m1 = (char *)m;
char *n1 = (char *)n;
return (strcmp(m1,n1));
}

int compare_long(const void *m, const void *n)
{
long *m1, *n1;
m1 = (long *)m;
n1 = (long *)n;
return (*m1 > *n1);
}
Dans cet exemple, la fonction tri_bulle est gnralise en
passant en paramtre la mthode permettant de comparer
les valeurs contenues dans le tableau. Avec compare_long, on
considre que le tableau contient des longs ; avec compare_
chaine_c on considre que le tableau contient des pointeurs
sur des chaines de type C. Dans tous les cas, il est ncessaire
que la taille dun lment du tableau soit gale la taille
dun pointeur. Il est impossible dutiliser ce tri_bulle avec
un tableau de caracres ASCII.
51
Passer un objet en paramtre
par pointeur/rfrence
Type1 fonction(, Type2* ptr, ); // par pointeur
Type1 fonction(, Type2& ref, ); // par rfrence
Passer un paramtre par pointeur ou par rfrence vite de
copier des objets complexes lors de leur passage des
fonctions. Cela permet dconomiser de la mmoire et du
temps.
AIIcnIon
Il faut absolument viter de recopier un objet lourd (du fait
de sa taille ou du temps que prendrait sa recopie) si cela nest
pas ncessaire. Il faut tre conscient que cela se fait de manire
implicite lorsquon le transmet une fonction (passage de
paramtre).
Toutefois, il peut exister un intrt crer une copie temporaire.
On peut ainsi la modifer souhait, sans toucher loriginal.
Lexemple 1 passe un paramtre par recopie.
MaClasse A;
//
void fonction(MaClasse B)
{
// B est une copie de A
B.methode();
// B est dtruit la fn de la fonction
}
//
fonction(A);
0cc|arcr un ponIcur sur unc foncIon
58 LhAPIJL 8 PonIcurs cI rcfcrcnccs
Lexemple 2 utilise un paramtre par rfrence. On ne recopie
plus lobjet, par contre une modifcation de B entrane une
modifcation de A. Il est possible de dclarer un paramtre
constant ( laide du mot-cl const) ; dans ce cas, tout appel
une fonction membre non const ou toute tentative de
modifcation dune variable membre de lobjet ( condition
quelle ne soit pas qualife de mutable) aboutira une
erreur de compilation.
MaClasse A;
//
void fonction(MaClasse& B)
{
B.methode();
}
void fonction(const MaClasse& B)
{
B.methode(); // erreur si MaClasse::methode non const
B.var = 0; // erreur
Type v = B.var; // ok
}
Enfn, lexemple 3 illustre un passage de paramtre par
pointeur. Toute modifcation de B entrane une modifca-
tion de A.
MaClasse* A = new MaClasse();
void fonction(MaClasse* B)
{
B->methode();
}
Info
La signature de ces trois fonctions est identique :
void f(int a[10]);
void f(int* a);
void f(int a[]);

4
L|asscs cI oh|cIs
La programmation oriente objet (POO), ou programma-
tion par objet, est un paradigme de programmation infor-
matique qui consiste en la dfnition et lassemblage de
briques logicielles appeles objets ; un objet reprsente
un concept, une ide ou toute entit du monde physique :
voiture, personne ou encore page dun livre. La programma-
tion oriente objet utilise des techniques comme lencapsu
lation, la modularit, le polymorphisme et lhritage. Ce chapitre
montre comment le langage C++ les met en uvre.
AIIcnIon
Ne perdez jamais de vue que le C++ est un langage orient
objet. Beaucoup semblent loublier lorsquils dcouvrent les pos-
sibilits orientes objet du C++. Ils semballent et, sous prtexte
de faire de lobjet, dfnissent des mthodes et encore des
mthodes Cest plus un dfaut quune bonne pratique. Il est
facile dinclure dans ses classes des choses qui nont rien y
faire. Pour vous aider, posez-vous cette question : la fonction-
nalit que jcris fait-elle partie de lobjet ou bien agit-elle
dessus ? En dautres termes : ne ngligez pas lutilit et le bien-
fond des fonctions.
80 LhAPIJL 4 L|asscs cI oh|cIs
Ajouter des donnes des objets
class MaClasse
{
type donnee;
};
Ajouter une donne un objet se fait de la mme manire
quen C avec les structures struct.
Lexemple suivant permet de dfnir lge dune personne
en ajoutant la donne membre m_age lobjet Personne.
class Personne
{
int m_age;
};
Objet
donne1
donne2
...
Nom de la classe
Champs (donnes)
Figure 4.1 : Reprsentation UML des donnes dun objet
On distingue deux types de donnes :
Celles que lobjet possde. Cest la composition. Dans ce
cas, la donne nat et meurt avec lobjet.
struct Voiture
{
Carburateur m_carbu;
};
Exemple de composition (trivial)
81
class Voiture
{
Carburateur* m_carbu;
public:
Voiture() { m_carbu = new Carburateur; }
~Voiture() { delete m_carbu; }
};
Exemple de composition (avec pointeur)
Objet
Objet1 donne1
Objet2 donne2
...
Nom de la classe
Champs (donnes)
Objet2
...
...
Objet1
...
...
Figure 4.2 : Reprsentation UML dune composition
Celles qui sont des liens vers un autre objet. C'est
lagrgation. Dans ce cas, la dure de vie de lobjet et de
la donne lie sont indpendantes. Dans lexemple
suivant, la dure de vie du carburateur ne dpend pas
de celui dune voiture.
{
Carburateur* m_carbu;
public:
Voiture() { m_carbu = 0; }
~Voiture() {}
void set_carburateur(Carburateur* c) { m_carbu = c; }
};
Exemple dagrgation
A|ouIcr dcs donnccs a dcs oh|cIs
82 LhAPIJL 4 L|asscs cI oh|cIs
Objet
Objet1 donne1
Objet2 donne2
...
Nom de la classe
Champs (donnes)
Objet2
...
...
Objet1
...
...
Figure 4.3 : Reprsentation UML dune agrgation
Lier des fonctions des objets
class MaClasse
{
type fonction_membre(arguments);
};
Pour lier une fonction un objet, ou plus exactement,
une instance dobjet, vous devez utiliser une fonction membre.
Vous pouvez lappeler avec loprateur . (point) ou ->
(fche) comme indiqu ci-aprs, selon quil sagit dune
instance de lobjet considr ou dun pointeur sur celle-ci.
Type instance, *instance_ptr;
instance.fonction_membre(arguments);
instance_ptr->fonction_membre(arguments);
AIIcnIon
La validit du pointeur sur une instance dune classe est sous
la responsabilit du programmeur. Un appel de fonction membre
avec un pointeur invalide peut provoquer un comportement
inattendu, mais pas forcment un plantage du programme. Un
appel avec un pointeur nul provoque le plus souvent un plan-
tage direct et plus facile dtecter.
88
Objet
donne1
donne2
...
fonction1()
fonction2(arguments)
...
Nom de la classe
Champs (fonctions)
Champs (donnes)
Figure 4.4 : Reprsentation UML des fonctions dun objet
Lexemple ci-aprs cre une simple classe reprsentant une
personne avec son ge et son nom (reportez-vous au
Chapitre 10 pour en savoir plus sur le type chane de
caractres utilis pour cette variable).
class Personne
{
std::string m_prenom, m_nom ;
int m_age ;
public :
//
int setNom(const std::string& n) ;
//
int getAge() const { return m_age ; }
void setAge(int a) const { m_age = a ; }
//
void affche(std::ostream& o) const
{
o << Nom : << m_nom << std::endl
<< Prenom : << m_prenom << std::endl
<< Age : << m_age << std::endl ;
}
} ;
// dans le fchier source
void Personne::setNom(const std::string& n)
{
m_nom = n ;
}
Lcr dcs foncIons a dcs oh|cIs
84 LhAPIJL 4 L|asscs cI oh|cIs
Voici maintenant un exemple dutilisation de cette classe :
Personne moi ;
moi.setAge( jeux_devinez_le() ) ;
moi.affche( std::cout ) ;
Dterminer la visibilit de
fonctions ou de donnes membres
class Classe
{
public :
//
protected :
//
private :
//
} ;
Les fonctions et donnes membres public sont visibles (ou
accessibles) par nimporte quelle partie du programme
utilisant la classe. Elles fournissent linterface publique de
la classe.
Les fonctions et donnes membres private ne sont visibles
que par les fonctions membres de la classe. Elles sont utili-
ses pour cacher les dtails dimplmentation.
Les fonctions et donnes membres protected sont visibles
par les fonctions membres de la classe ou de ses classes
flles directes (par hritage). Elles ne sont pas visibles du
reste du programme.
85
Info
Les class sont private par dfaut (tant pour lhritage que
pour les membres prcdant la premire spcifcation de visi-
bilit), alors que les struct sont public par dfaut.
class MaClasse : /* private */ ClasseMere { } ;
struct MaClasse : /* public */ ClasseMere { } ;

Il est possible de reprsenter sous forme dune hirarchie de
classes, parfois appele arborescence de classes, la relation de
parent qui existe entre les diffrentes classes. Larborescence
commence par une classe gnrale appele superclasse (par-
fois classe de base, classe parent, classe anctre, classe mre ou
classe pre, les mtaphores gnalogiques sont nombreuses).
Puis les classes drives (classe flle ou sousclasse) deviennent
de plus en plus spcialises. Ainsi, on peut gnralement
exprimer la relation qui lie une classe flle sa mre par la
phrase est un (de langlais is a ).
Objet
+ donne1
# donne2
- donne3
+ fonction1()
# fonction2(arguments)
- fonction3(arguments)
public
protg
priv
public
protg
priv
Nom de la classe
Champs (fonctions)
Champs (donnes)
Figure 4.5 : Reprsentation UML de la visibilit des membres
0cIcrmncr |a vsh|Ic dc foncIons ou dc donnccs mcmhrcs
88 LhAPIJL 4 L|asscs cI oh|cIs
AsIucc
Grce au mot-cl friend (ami), il est possible de rendre acces-
sible les donnes et fonctions prives dune classe :
une fonction particulire, dfnie nimporte o dans le
programme ;
une classe extrieure dtermine ;
une fonction particulire dune classe extrieure
dtermine.
Le mot-cl friend est par exemple ncessaire lorsque lon veut
implmenter des oprateurs globaux qui utilisent des lments
de ladite classe.
Pour donner laccs une fonction, vous pouvez procder comme
suit :
class X
{
int a;
friend void f ( X* );
};
void f (X * p)
{
p->a = 0;
}
void main ()
{
X * ptr = new X;
f (ptr);
}
Pour donner laccs une classe, vous pouvez procder comme
suit :
class B;
class A
{
private:
int a;
f();
friend B;
};
81
class B
{
void h (A*p) { p->a = 0; p->f(); }
};
Pour donner laccs une fonction membre dune autre classe,
vous pouvez procder comme suit :
class B;
class A
{
private:
int a;
friend void B::f();
};
class B
{
void f(A * p) { p->a = o; }
};

Expliciter une instance
avec le pointeur this
type MaClasse::fonction_membre(arguments)
{

this->variable_membre = ;

return valeur;
}
Le pointeur this correspond ladresse mmoire de
linstance ayant servi pour lappel de la fonction membre.
Son utilisation nest pas obligatoire, sauf pour lever une
ambigut (par exemple lorsquune variable membre de la
Lxp|cIcr unc nsIancc avcc |c ponIcur this
88 LhAPIJL 4 L|asscs cI oh|cIs
classe porte le mme nom quun argument de la fonction
membre).
Le pointeur this nest disponible que dans limplmenta-
tion dune fonction membre.
AsIucc
Lutilisation systmatique de this pour accder des membres
de la classe se rvle tre une bonne pratique lusage. Elle
rend vidente laccs ces derniers ; la lourdeur apparente de
cette syntaxe a pour contrepartie une comprhension accrue,
facilite, du code.
Dfnir un constructeur/
destructeur
class Objet
{
public:
Objet(); // constructeur par dfaut
Objet(const Objet&); // constructeur par copie
Objet(paramtres); // constructeur
~Objet(); // destructeur
};
Les constructeurs et le destructeur dun objet ressemblent,
quelques dtails prs, des fonctions membres :
ils nont pas de type de retour ;
ils portent le mme nom que lobjet.
Le destructeur possde en plus les caractristiques suivantes :
son nom commence par un ~ (tilde) ;
il na pas dargument.
80
Pour toute instanciation de classe, un constructeur est obli-
gatoirement appel. Si aucun constructeur nexiste, le com-
pilateur en gnre un automatiquement. Ce dernier consiste
appeler le crateur par dfaut pour chacun des membres
de la classe, lorsquil existe ou quil peut tre gnr.
AIIcnIon
Lhritage est cens garantir lordre dappel des destructeurs.
Par exemple, si C hrite de B qui hrite elle-mme de A, lors
de la destruction de dune instance de C les destructeurs
doivent tre appels dans lordre inverse, soit : C::~C, B::~B
puis A::~A. Pourtant, ce nest pas toujours le cas, notamment
avec certains vieux compilateurs. Prenez donc lhabitude dtre
prudent et partez du postulat que ce nest gnralement pas
le cas.
Ajoutons maintenant un constructeur et un destructeur
notre classe Personne.
class Personne
{
//
public:
Personne(std::string prenom, std::string nom, int age=0)
: m_prenom(prenom), m_nom(nom), m_age(age)
{
std::cout << m_prenom << << m_nom
<< vient de natre\n;
}
~Personne()
{
std::cout << m_prenom << << m_nom
<< vient de mourir\n;
}
//
};
0cnr un consIrucIcurjdcsIrucIcur
10 LhAPIJL 4 L|asscs cI oh|cIs
Et utilisons-le :
//
{
Personne reMoi(Vincent, Gouvernelle);
//
}
//
Lors de lexcution du code prcdent, nous obtiendrons
cet affchage sur la console :
Vincent Gouvernelle vient de natre
Vincent Gouvernelle vient de mourir
La premire ligne apparat lors de linstanciation de la classe. La
deuxime apparat lors de la destruction de celle-ci la fn
du bloc.
Empcher le compilateur de
convertir une donne en une autre
class Objet
{
public:
explicit Objet(paramtres); // constructeur
};
La surcharge de fonction implique de manire sous-
jacente des tentatives de conversion des paramtres. Cela
peut tre indsirable, voire dangereux. Pour interdire au
11
compilateur de tenter de convertir une donne en une
autre par lintermdiaire dun constructeur, vous avez la
possibilit de rendre ce dernier explicit.
struct Age
{
int valeur;
Age(int a) : valeur(a) {}
};
void fonction(Age a);
//
fonction(34); // OK : 34 implicitement converti en

Age(34)
struct Age
{
int valeur;
explicit Age(int a) : valeur(a) {}
};
void fonction(Age a);

//
fonction(34); // Erreur
fonction(Age(34)); // OK : lutilisateur rend

explicite sa volont
AsIucc
Le mot-cl explicit permet galement de simuler avec le C++,
dans une certaine mesure, un langage typage fort comme
Pascal ou Ada.
Lmpchcr |c comp|aIcur dc convcrIr unc donncc cn unc auIrc
12 LhAPIJL 4 L|asscs cI oh|cIs
Spcifer quune fonction
membre ne modife pas
lobjet li
class Objet
{
//
type fonction(arguments) const;
//
mutable type variable;
};
Une fonction spcife comme const ne peut ni appeler
dautres fonctions membres non const, ni modifer ses
variables membres (sauf si elles sont mutable). Mentionnez
ds que possible ce spcifcateur, car un objet pass en
rfrence constante (const type &) ne peut appeler que des
fonctions membres const.
Info
Nabusez pas du spcifcateur mutable pour dtourner const.
Dune manire gnrale, cela traduit un dfaut de conception
de votre architecture logicielle.
18
Rendre une fonction/donne
membre indpendante de
lobjet li
class Objet
{
static type variable;
public:
static type fonction(arguments);
};
Les membres static dune classe ne sont pas lis une
instance de cette dernire. Ils agissent comme des variables
globales ou des fonctions traditionnelles, mais sont concep-
tuellement lis la classe.
Pour illustrer ceci, examinons rapidement une implmen-
tation simple du pattern Singleton. Lobjet du singleton est
de restreindre linstanciation dune classe un seul objet
(ou bien quelques objets seulement). Il est utilis par
exemple lorsque lon a besoin dexactement un objet pour
coordonner des oprations dans un systme.
class Singleton
{
static Singleton* unique_instance;
int status;
Singleton();
public:
static Singleton* get_instance() const;
// Autres dclarations
int get_status() const;
};
Pattern Singleton (dclaration)
cndrc unc foncIonjdonncc mcmhrc ndcpcndanIc dc |oh|cI |c
14 LhAPIJL 4 L|asscs cI oh|cIs
Singleton* Singleton::unique_instance = 0;
static Singleton* Singleton::get_instance() const
{
if (unique_instance == 0)
unique_instance = new Singleton;
return unique_instance;
}
int Singleton::get_status() const
{
return status;
}
Pattern Singleton (implmentation)
int s = Singleton::get_instance()->get_status();
Pattern Singleton (utilisation)
Comprendre le changement
de visibilit lors de lhritage
class Fille : public Parente { };
class Fille : private Parente { };
class Fille : protected Parente { };
Info
Lhritage est une notion essentielle dans la programmation
objet. Lhritage consiste runir les dfnitions dune (hri-
tage simple) ou plusieurs classes (hritage multiple) et de leur
adjoindre un ensemble de membres spcifques. Cette nouvelle
classe est communment appele classe drive .
15
ObjetA
ObjetB
classe mre
classe drive
Figure 4.6 : Reprsentation UML de lhritage
La drivation peut tre de trois types : public, protected
(protg) ou private (priv). Selon le type de drivation,
la visibilit des membres de la classe parente change. Le
tableau suivant rsume les diffrents cas.
Visibilit des membres parents en fonction du type de drivation
L|assc parcnIc hcrIagc prvc hcrIagc proIcgc hcrIagc puh|c
inaccessible inaccessible inaccessible inaccessible
prive inaccessible inaccessible inaccessible
protge prive protg protg
publique prive protg public
Pour bien comprendre cela, considrons la classe mre sui-
vante :
class A
{
public:
void func_publique() {}
protected:
void func_protegee() {}
private:
void func_privee() {}
};
Lomprcndrc |c changcmcnI dc vsh|Ic |ors dc |hcrIagc
18 LhAPIJL 4 L|asscs cI oh|cIs
Lhritage public engendre les visibilits suivantes :
class B : public A
{
public:
void test_call()
{
A::func_publique(); // vue comme publique
A::func_protegee(); // vue comme protge
//A::func_privee(); // erreur : est inaccessible
}
};
void B_test_use()
{
B b;
b.func_publique(); // vue comme publique
//b.func_protegee(); // vue comme protge
//b.func_privee(); // est inaccessible
}
Lhritage protg engendre les visibilits suivantes :
class C : protected A
{
public:
void test_call()
{
A::func_publique(); // vue comme protge
A::func_protegee(); // vue comme protge
//A::func_privee(); // est inaccessible
}
};
void C_test_use()
{
C c;
//c.func_publique(); // vue comme protge
//c.func_protegee(); // vue comme protge
//c.func_privee(); // est inaccessible
}
11
Lhritage priv engendre les visibilits suivantes :
class D : private A
{
public:
void test_call()
{
A::func_publique(); // vue comme prive
A::func_protegee(); // vue comme prive
//A::func_privee(); // est inaccessible
}
};
void D_test_use()
{
D d;
//d.func_publique(); // vue comme prive
//d.func_protegee(); // vue comme prive
//d.func_privee(); // est inaccessible
}
tendons maintenant notre class Personne pour en faire un
employ. Un employ reoit un salaire et peut pointer le
matin et le soir.
class Employe : public Personne
{
double m_salaire;
public:
Employe() : Personne(,), m_salaire(0) {}
void pointer_matin(Heure) { }
void pointer_soir(Heure) { }
};
Lomprcndrc |c changcmcnI dc vsh|Ic |ors dc |hcrIagc
18 LhAPIJL 4 L|asscs cI oh|cIs
Comprendre les subtilits
de lhritage multiple
class Fille : derivation Parent1, derivation

Parent2, { };
Comme nous lavons dit la section Comprendre le
changement de visibilit lors de lhritage , lhritage
peut tre multiple. Il en rsulte certaines subtilits quil est
essentiel de connatre pour matriser cette technique. Pour
utiliser sainement lhritage multiple, il vaut mieux le voir
comme un moyen dajouter une classe flle un ensemble
de mthodes et dattributs de telle sorte que cela ne
remette pas en cause ce dont elle hritait dj par ailleurs.
B B
CL
M
Figure 4.7 : Reprsentation UML de lhritage multiple.
Le premier problme de lhritage multiple est le clonage
de donne, comme le montre lexemple suivant.
class CL { };
class A : public CL { };
class B : public CL { };
class M : public A, public B
{

M() : A(), B() { }

};
10
Dans ce cas, la classe CL est duplique en mmoire. Si lon
veut accder lune ou lautre des donnes dune instance
de CL, il est alors ncessaire de prciser par quelle branche
dhritage il faut passer. Cela ce fait grce un transtypage
multiple. Dans le cadre de notre exemple, on a les deux
possibilits suivantes :
CL* clPtr = (CL*) (A*) mPtr ;
CL* clPtr = (CL*) (B*) mPtr.
Empcher la duplication de
donnes avec lhritage virtuel
class Fille : type_de_derivation virtual Parent1,

{ };
Dans certains cas, lhritage multiple engendre la duplica-
tion de classes en mmoire. Cest le cas lorsquen remon-
tant dans lhritage, un ou plusieurs types de classe
apparaissent plusieurs fois. Le mot-cl virtual doit tre
rpt si ncessaire, comme pour le type de drivation.
Lexemple ci-aprs montre comment empcher cette
duplication mmoire, grce lhritage virtuel.
class U { };
class A : public virtual U { };
class B : public virtual U { };
class M : public A, public B
{

M() : U(), A(), B() { }

};
Lmpchcr |a dup|caIon dc donnccs avcc |hcrIagc vrIuc|
80 LhAPIJL 4 L|asscs cI oh|cIs
Comme nous venons de le dire, le principe de lhritage
virtuel est dviter la duplication des donnes dune classe
parente apparaissant plusieurs fois dans la hirarchie de
lhritage. Cela est pratique mais implique de devoir pr-
ciser la construction de toutes les classes dont on hrite
virtuellement, et ce chaque nouvel hritage.
Cest pourquoi, bien souvent, les programmeurs C++ se
limitent lhritage simple autant que possible. Ils nutili-
sent lhritage multiple quavec parcimonie, en prenant
soin dviter les cas o une classe apparat plusieurs fois
dans une hirarchie. Lhritage virtuel nest en effet que
trs peu utilis, car dans une hirarchie complexe, il devient
vite trs complexe.
Une mthode virtuelle de la classe commune U peut tre
redfnie dans A ou B. Trois cas se prsentent alors :
si elle nest redfnie ni dans A ni dans B, alors celle de U
sera utilise ;
si elle est redfnie seulement dans A ou B, alors cette
dernire sera utilise et pas celle de U ;
si elle est redfnie dans A et dans B, alors le compilateur
ne peut choisir.
Bien entendu, si elle est redfnie aussi dans M, la redfni-
tion de M aura priorit sur les autres.
Simuler un constructeur virtuel
class Objet
{
public:
virtual ~Objet() {}
virtual Objet* clone() = 0;
virtual Objet* create() = 0;
81
};
class Type : public Objet
{
public:
virtual Type* clone() { return new Type(*this);
}
virtual Type* create() { return new Type(); }
};
Le langage C++ ne supporte pas directement les construc-
teurs virtuels. Il est nanmoins possible de les simuler par
un idiome. Il est ainsi possible dobtenir le mme effet
quun constructeur virtuel grce lutilisation dune fonc-
tion membre virtuelle clone() pour le constructeur par
copie, ou dune fonction membre virtuelle create() pour
le constructeur par dfaut. Vous pouvez bien sr les appe-
ler comme bon vous semble, mais les noms employs ici
sont ceux que lon retrouve traditionnellement dans une
telle situation.
Le principe est simple. La fonction membre clone()
appelle le constructeur par copie, ou tout autre code plus
complexe, dans le but de copier ltat de linstance actuelle
dans un nouvel objet de mme type : cest un clone. La
fonction membre create() appelle simplement le construc-
teur par dfaut de la classe concerne : elle cre une nou-
velle instance neuve de mme type.
void fonction(Objet& objet)
{
Objet* obj1 = objet.clone();
Objet* obj2 = objet.create();
//
delete obj1; // vous comprenez ici la ncessit
// du destructeur virtuel
delete obj2;
}
Smu|cr un consIrucIcur vrIuc|
82 LhAPIJL 4 L|asscs cI oh|cIs
Le code ci-avant fonctionne quel que soit le sous-type
dobjet utilis. Il permet de crer une copie ou une nou-
velle instance de mme type que lobjet fourni en para-
mtre sans le connatre lavance.
Info
Le type de retour des fonctions membres clone() ou create()
est intentionnellement diffrent du type de retour de la classe
de base. Ce mcanisme sappelle covariant return type ou, en
franais, type de retour covariant . Il nest pas support par
tous les compilateurs, surtout sils ne sont pas rcents. Si cest le
cas du vtre, vous naurez pas dautres moyens que de conserver
le type de retour de la classe de base, Objet* dans notre cas.
Crer un type abstrait
laide du polymorphisme
class Classe
{
virtual Type Nom(arguments) = 0;
virtual Type Nom(arguments) const = 0;
};
Une classe devient abstraite partir du moment o elle
contient au moins une fonction virtuelle pure. Il devient dans
ce cas impossible de linstancier. On appelle parfois les
classes abstraites des ADT (abstract data types) ou, en fran-
ais, types de donnes abstraits . Lide est dimposer
aux concepteurs des classes drives de redfnir et dimpl-
menter ces fonctions. Il est ainsi possible dutiliser ces
fonctionnalits avant mme leur implmentation.
88
class Forme
{
public:
virtual foat Aire() = 0;
};
class Carre : public Forme
{
public:
virtual foat Aire() { return m_cote * m_cote; }
private:
foat m_cote;
};
class Cercle : public Forme
{
public:
virtual foat Aire() { return 3.1415926535*

m_rayon*m_rayon; }
private:
foat m_rayon;
};
Grce aux fonctions virtuelles, on peut crer un algo-
rithme en nutilisant que la classe de base qui va automa-
tiquement appeler les fonctions des classes drives.
En proposant dutiliser un mme nom de mthode pour
plusieurs types dobjets diffrents, le polymorphisme permet
une programmation beaucoup plus gnrique. Le dve-
loppeur na pas savoir, lorsquil programme une mthode,
le type prcis de lobjet sur lequel la mthode va sappli-
quer. Il lui sufft de savoir que cet objet implmentera la
mthode.
Lrccr un Iypc ahsIraI a |adc du po|ymorphsmc
84 LhAPIJL 4 L|asscs cI oh|cIs
Ainsi, un logiciel de calcul dintrt pour des comptes
bancaires se prsenterait de la faon suivante (en pseudo-
code) dans le cadre dune programmation classique :
si type de <MonCompteBancaire> est un:
PEA => MonCompteBancaire->calculeInteretPEA()
PEL => MonCompteBancaire->calculeInteretPEL()
LivretA => MonCompteBancaire->calculeInteretLivretA()
fn du choix
Si un nouveau type de compte bancaire PERP apparat (et
avec lui un nouveau calcul), il sera ncessaire dune part
dcrire la nouvelle mthode calculeInteretPERP(), mais
aussi de modifer tous les appels du calcul donn ci-dessus.
Dans le meilleur des cas, celui-ci sera isol et mutualis de
sorte quune seule modifcation sera ncessaire. Dans le pire
des cas, il peut y avoir des centaines dappels modifer.
Avec le polymorphisme, toutes les mthodes porteront le
mme nom, par exemple calculeInteret(), mais auront
des implmentations diffrentes : une par type de compte.
Lappel sera de la forme :
MonCompteBancaire->calculeInteret()
Lors de larrive du nouveau compte, aucune modifca-
tion de ce code ne sera ncessaire. Le choix de la mthode
relle utiliser sera fait automatiquement lexcution par
le langage, alors que dans le cas prcdent cest le dve-
loppeur qui devait programmer ce choix.
Info
Lorsquune classe ne contient que des fonctions membres vir-
tuelles pures, on parle alors de classe interface. Dans certains
langages, comme Java, cette notion est directement dfnie.
85
Utiliser lencapsulation
pour scuriser un objet
class MaClasse
{
//
private: // ou protected:
Type mon_objet_encapsule;
Type* mon_objet_encapsule2;
//
public:
Type2 methode();
};
Lencapsulation consiste masquer le contenu dun objet et
ne mettre disposition que des mthodes permettant de
manipuler cet objet. En forant lutilisateur de la classe
utiliser des fonctions membres (plutt que directement les
donnes), lencapsulation permet dassurer la cohsion
interne dun objet.
Lobjet peut tre ainsi vu comme une bote noire, laquelle
sont associs des proprits et/ou des comportements.
Limplmentation est cache et peut tre change sans
impact sur le reste du code, condition bien sr que le
changement dimplmentation ne change pas le compor-
tement de lobjet. Lencapsulation permet donc de sparer
la spcifcation, ou dfnition, dun objet de son impl-
mentation.
En troisime lieu, lencapsulation peut permettre de cacher
totalement la manire dont un objet est implment. Cela
peut savrer particulirement utile si vous voulez crer
une bibliothque sans laisser fltrer vos secrets de fabrication.
uI|scr |cncapsu|aIon pour sccurscr un oh|cI
88 LhAPIJL 4 L|asscs cI oh|cIs
Lexemple suivant vous montre comment :
// Fichier en-tte
class ClassePrivee;
class ClasseVendue
{
ClassPrivee *implementation;
public:
Type methode();
};

// Fichier source
class ClassePrivee
{
// donnes
public:
Type methode();
};
Type ClasseVendue::methode()
{
implementation->methode();
}
Obtenir des informations
de types dynamiquement
#include <typeinfo>
class type_info
{

public:
virtual ~type_info();
bool operator==(const type_info&) const;
bool operator!=(const type_info&) const;
int before(const type_info&) const;
const char* name() const;
};
class bad_cast : public exception;
class bad_typeid : public exception;
type_info typeid();
81
Nous avons dj parl de dynamic_cast<> dans la section
sur les conversions. Le C++ dfnit galement la fonction
typeid(). Elle permet dobtenir en temps constant, cest-
-dire indpendamment de la taille ou de la complexit de
lobjet , des informations sur une classe ou une instance
de celle-ci grce aux informations dynamiques de type (de
langlais runtime type information, RTTI). Cette classe diffre
souvent selon les compilateurs, mais fort heureusement
une trame commune se retrouve dans ces diverses impl-
mentations.
Tout dabord, il faut savoir quil nest pas possible de crer
soi-mme des instances de classe type_info. La seule manire
est de passer par la fonction typeid(), disponible travers les
fchiers den-tte typeinfo. Il est galement impossible de
copier ou daffecter des objets de type type_info.
Les oprateurs == et != permettent de tester lgalit et
lingalit de type travers les objets type_info. Contraire-
ment un dynamic_cast, qui effectue un test du type est
compatible , ces oprateurs effectuent bien un test du
type est un . Cela na pas la mme vocation mais est trs
utile dans certains cas.
Il ny a aucun lien entre lordre de collecte des types et
les relations dhritage. Vous pouvez utiliser la fonction
membre before() pour dterminer lordre de collecte
des types. Il ny a aucune garantie que cette fonction
retourne le mme rsultat selon le programme, voire
mme selon lexcution dun mme programme. Sous ce
rapport, cette fonction a le mme genre de comporte-
ment que loprateur &.
La fonction membre name() renvoie le nom du type de
lobjet. Parfois, ce nom est partiellement dcor ; cela dpend
principalement du compilateur utilis. Je vous dconseille
donc fortement dutiliser cette valeur comme appui dans
vos programmes.
0hIcnr dcs nformaIons dc Iypcs dynamqucmcnI
88 LhAPIJL 4 L|asscs cI oh|cIs
Info
Le type de retour de la fonction membre before() peut varier
selon les compilateurs. Par exemple, Visual Studio 2008
retourne un int, alors que g++ 3.4.2 renvoie un bool.
Le fchier den-tte typeinfo fournit galement la dfni-
tion de deux exceptions bad_cast et bad_typeid. La pre-
mire peut tre leve lors dun dynamic_cast invalide. La
deuxime le sera lors dun appel typeid() sur une expres-
sion invalide, telle un pointeur nul.
Transformer un objet en fonction
struct
{
type operator()(arguments) const;
};
Les foncteurs sont une abstraction des fonctions sous forme
dobjet-fonction laide de loprateur parenthses. Les
foncteurs sont largement utiliss par la bibliothque stan-
dard STL.
quoi bon les foncteurs puisquon dispose des fonctions ?
Ils sont en fait un peu plus puissants que les fonctions.
Ils permettent par exemple dembarquer des paramtres
supplmentaires en plus du code de la fonction elle-mme.
Ils sont aussi utilisables comme paramtre de patron dalgo-
rithme (algorithm templates), le plus souvent sous forme
dobjet temporaire.
Lexemple ci-aprs illustre laddition lment par lment
du contenu de deux tableaux a et b. Le rsultat est stock
dans le premier tableau. Les deux tableaux contiennent des
double et sont de mme taille.
80
std::transform(a.begin(), a.end(), b.begin(),

a.begin(), std::plus<double>());
Cet autre exemple montre comment inverser (x = -x)
chaque lment :
std::transform(a.begin(), a.end(), a.begin(),

std::negate<double>());
Les fonctions daddition et de ngation sont inlines impli-
citement. Ce qui rend le code au moins aussi performant
que si vous laviez crit vous-mme, mais surtout plus syn-
thtique et comportant moins de risque derreur lors de
lcriture.
Voici encore quelques exemples utiles :
std::vector<int> V(100);
std::generate(V.begin(), V.end(), rand);
Remplir un tableau avec des nombres alatoires
struct plus_petit_abs :
public std::binary_function<double, double, bool>
{
bool operator() (double x, double y)
{
return fabs(x) < fabs(y);
}
};
std::vector<double> V;
//
std::sort(V.begin(), V.end(), plus_petit_abs());
Trier les lments dun tableau en ignorant leur signe
Jransformcr un oh|cI cn foncIon
00 LhAPIJL 4 L|asscs cI oh|cIs
struct Somme : public std::unary_function<double, void>
{
Somme() : somme(0) {}
void operator()(double valeur) { somme+=valeur; }
double somme;
};
std::vector<double> V;
//
Somme resultat = std::for_each(V.begin(), V.end(), Somme());
std::cout << Somme = << resultat.somme << std::endl;
Somme des lments dun tableau illustrant lavantage des
foncteurs sur les fonctions
std::list<int> L;
//
std::list<int>::iterator it;
it = std::remove_if(L.begin(), L.end(), std::compose2(
std::logical_and<bool>(),
std::bind2nd(std::greater<int>(), 100),
std::bind2nd(std::less<int>(), 1000) ));
L.erase(it, L.end());
Suppression des lments (compris entre 100 et 1 000) dune
liste illustrant limbrication de foncteurs
struct Objet
{
void affche() { cout << /* */ ; }
};
std::vector<Objet> V(100);
std::for_each(V.begin(), V.end(),

std::mem_func<void,Objet>(&Objet::affche));
Affcher tous les lments dun tableau via la fonction membre
de lobjet utilis
01
AsIucc
Tous les foncteurs standard drivent des deux classes, unary_
function et binary_function. Elles ne contiennent que des
typedef. Cela peut paratre totalement inutile, mais facilite
grandement la programmation gnrique. Utilisez cette techni-
que si vous dcidez dcrire vos propres foncteurs.
Voici pour mmoire et titre dexemple le contenu de ces deux
classes :
template <class _Arg, class _Result>
struct unary_function
{
typedef _Arg argument_type; // le type de largument
typedef _Result result_type; // le type de retour
};
template <class _Arg1, class _Arg2, class _Result>
struct binary_function
{
typedef _Arg1 frst_argument_type; // le type du premier

argument
typedef _Arg2 second_argument_type; // le type du

deuxime argument
typedef _Result result_type; // le type de retour
};

Info
Si vous regardez les fchiers den-tte de la bibliothque STL,
vous rencontrez certainement la notion de gnrateur (gene-
rator), notamment dans le nommage de certains paramtres
des patrons (templates). Cette notion correspond simplement
un foncteur ne prenant pas dargument. On pourrait la repr-
senter par cette classe de base :
template <class _Result>
struct generator
{
typedef _Result result_type; // le type de retour
};
Les gnrateurs qui en hriteraient nauraient plus qu dfnir
loperator()() sans argument.
Jransformcr un oh|cI cn foncIon
02 LhAPIJL 4 L|asscs cI oh|cIs
La STL prdfnit plusieurs types de foncteurs dans le
fchier den-tte <functional>. Voici un rcapitulatif de
son contenu.
Foncteur sur les oprateurs standard
FoncIcurs 0pcraIcur FoncIcurs 0pcraIcur
arIhmcIqucs assocc |ogqucs assocc
plus + equal_to ==
minus - not_equal_to !=
multiplies * greater >
divides / less <
modulus % greater_equal >=
negate - (unaire) less_equal <=
logical_and &&
logical_or
||
logical_not ! (unaire)
Inverseurs logiques
FoncIcur hc|pcr Lodc cquva|cnI a |cxccuIon
unary_negate not1
1
not1(pred)(a) quivaut ! pred(a)
binary_negate not2
1
not2(pred)(a,b) quivaut ! pred(a,b)
1. Les fonctions not1 et not2 prennent un prdicat en argument et retour-
nent, respectivement, une instance de unary_negate ou une instance de
binary_negate.
Binders : pour fxer des paramtres
FoncIcur hc|pcr Lodc cquva|cnI a |cxccuIon
binder1st bind1st
1
bind1st(std::minus<foat>,1.3)
(a) quivaut 1.3 - a
binder2d bind2nd
1
bind2nd(std::minus<foat>,1.3)
(a) quivaut a - 1.3
1. Les fonctions bind1st et bind2nd prennent un prdicat en argument et
retournent, respectivement, une instance de binder1st ou une instance de
binder2nd.
08
Adaptateur de pointeur de fonctions : transformer des fonctions
en foncteurs
FoncIcur hc|pcr
pointer_to_unary_function ptr_fun
pointer_to_binary_function ptr_fun
Adaptateur de pointeur de fonctions membres :
transformer des fonctions en foncteurs
Jypc hc|pcr 0cscrpIon
mem_fun_t mem_fun Sert appeler une fonction
membre.

mem_func_t(p_func)(arg)
quivaut (*arg->*p_func)().
const_mem_fun_t mem_fun Idem pour une fonction
membre const
mem_fun_ref_t mem_fun Sert appeler une fonction
membre par rfrence.

mem_func_t(p_func)(arg)
quivaut (*arg.*p_func)().
const_mem_fun_ref_t const_mem _fun_ref Idem pour une fonction
membre const.
mem_fun1_t mem_fun Sert appeler une fonction
membre un paramtre.

mem_func_t(p_func)(arg1,arg2)
quivaut (*arg1->* p_func)
(arg2).
const_mem_fun1_t mem_fun Idem pour une fonction
membre const
mem_fun1_ref_t mem_fun Sert appeler une fonction
membre un paramtre, par
rfrence.

mem_func_t(p_func)(arg1,arg2)
quivaut (*arg1.*p_func)
(arg2) .
const_mem mem_fun_ Idem pour une fonction
fun1_ref_t membre const.
Jransformcr un oh|cI cn foncIon
04 LhAPIJL 4 L|asscs cI oh|cIs
Foncteurs spcifques
Jypc P|aIc-formc 0cscrpIon hc|pcr
_Identity 1 Voir identity
_Select1st 1 Voir select1st
_Select2nd 1 Voir select2nd
identity_element 2 4 Pour std::plus<_T>
retourne _T(0), pour
std::multiplies<_T>
retourne _T(1)
identity 2 3 4 Retourne largument
tel quel
select1st 2 3 4 Prend un std::pair<>
en argument et
retourne arg.frst
select2nd 2 3 4 Prend un std::pair<>
en argument et
retourne arg.second
project1st 2 3 4 Retourne le
premier argument
project2nd 2 3 4 Retourne le
deuxime argument
unary_compose 2 3 4 unary_functor(F1,F2)(x)
quivaut F1(F2(x)) compose1
binary_compose 2 3 4 unary_functor(F1,F2,F3)(x)
quivaut F1(F2(x),F3(x)) compose2
substrative_rng 2 4 Gnrateur de nombres
pseudo-alatoires bas sur
la mthode soustractive
employe en FORTRAN
1. GCC 3.4
2. GCC 3.4 via <ext/functional>
3. VC++2008 avec _HAS_TRADITIONAL_STL
4. SGI
5
Jcmp|aIcs cI
mcIaprogrammaIon
Le template est une technique de programmation gnri-
que favorisant lindpendance du code par rapport au
type, et ventuellement au nombre darguments utiliss.
Ce concept est trs important car il permet daugmenter
le niveau dabstraction du langage de programmation.
La mtaprogrammation consiste utiliser les modles de telle
sorte que le code source soit directement excut par le
compilateur. Ces mtaprogrammes peuvent gnrer des
constantes ou des structures de donnes. Cette technique
est largement utilise en C++, et on la retrouve notam-
ment dans la bibliothque BOOST.
JraducIon
Comment traduire template en bon franais ? Le mot le plus
proche dans notre langue se trouve dans le domaine de la cou-
ture : patron . Vous rencontrerez peut-tre aussi le terme
modle . En couture, un patron sutilise un peu comme un
calque pour dcouper des pices de tissus. On est ainsi sr dobte-
nir la mme forme pour chaque vtement produit. Mais il est
bien sr possible de changer le type dtoffe. Je trouve lanalogie
08 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
particulirement bien choisie, mais pour obtenir une traduction
vraiment comprhensible, il serait prfrable dutiliser une
expression comme patron de classe bien quun peu longue
mon got.
Dans le prsent ouvrage, jai prfr garder langlicisme pour la
concision. Deux raisons sajoutent celle prcite. La premire est
quil correspond au mot-cl du langage lui-mme. La deuxime
raison est que lusage de cet anglicisme est largement accept.
Crer un modle de classe
rutilisable
template <(class
|
typename) T1 [, ]>
class Objet [: ]
{
};
Objet<Type1 [, ]> objet;
template <(class
|
typename) T1 [, ]>
Type1 fonction(Type2 param [, ]);
Type1 res = fonction[<Type,[,]>](, t1, );
La notion de modle (de langlais template) est large-
ment utilise dans la STL et dans BOOST. Il est ncessaire
de bien la comprendre pour tirer pleinement partie du
langage C++. Les templates permettent de sparer la
forme du fond, en laissant la charge du compilateur la
rcriture dun mme algorithme (le fond) dautres types
de donnes (la forme). On peut donc voir les paramtres
templates comme un moyen de paramtrer les types dune
structure ou dune fonction, rendant ces dernires ind-
pendantes du ou des types de donnes manipuls.
01
Pour mettre en uvre un template, il faut imprativement
prciser avec quels types on lutilise. La seule exception o
lon peut omettre cette qualifcation a lieu lors de lappel
une fonction template pour laquelle il ny a aucune
ambigut de rsolution dappel. Un exemple bien connu
de fonction template sont les fonctions min et max fournit
avec la STL (attention, Microsoft persiste ne pas les four-
nir mais les remplace par ses vieilles macros min(a,b) et
max(a,b)). Le code suivant est une version simplife de
celle fournie par la STL de g++ :
template <typename _Tp>
inline const _Tp& min(const _Tp& __a, const _Tp& __b)
{
if (__b < __a)
return __b;
return __a;
}

template<typename _Tp>
inline const _Tp& max(const _Tp& __a, const _Tp& __b)
{
if (__a < __b)
return __b;
return __a;
}
Ces fonctions sont plus puissantes que des macros, car elles
assurent de ne pas calculer deux fois des valeurs (avant
comparaison et retour du min ou du max). Et elles illustrent
parfaitement le paramtrage dune fonction avec des types,
grce au template.
Linstanciation dune fonction template, comme nous lavons
dit, peut se faire explicitement, mais aussi implicitement.
Par exemple, un appel std::min(1,2) est suffsant. Dans ce
cas, 1 et 2 sont toutes deux des constantes entires et le
compilateur comprend aisment quil faut instancier std::
min<int>(). Par contre, lors dun appel std::min(1,2.0), le
Lrccr un modc|c dc c|assc rcuI|sah|c
08 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
compilateur ne sait plus quoi faire (sauf sil existe une fonc-
tion min(int,double) dans lespace de nom std). Ici, il sera
ncessaire demployer une instanciation explicite : std::
min<int>(1,2.0) pour transformer 2.0 en valeur entire,
ou std:min<double>(1,2.0) pour transformer 1 en rel
double prcision.
Le compilateur utilise la loi du moindre effort pour ins-
tancier un template. Par exemple, utiliser un pointeur sur
un objet template ne sufft provoquer son instanciation.
Celle-ci naura lieu que lors du drfrencement de celui-
ci. De mme, seules les fonctionnalits utilises dune
classe template sont, par dfnition, instancies.
Par exemple, dans lexemple ci-aprs, seule la mthode
affche() sera instancie. Ce programme compile donc
parfaitement, mme si la mthode non_Codee() nest pas
implmente.
#include <iostream>
template <typename T>
class Exemple
{
public:
void affche();
void non_Codee();
};
template <typename T>
void Exemple<T>::affche()
{
std::cout << Je maffche(). << std::endl;
}
// la mthode Exemple<T>::non_Codee() nest pas implmente
int main(int,char**)
{
// instanciation de Exemple<char>
Exemple<char> ex;
// instanciation de Exemple<char>affche()
ex.affche();
}
00
c|ass ou Iypcnamc ?
Dans des paramtres templates, les mots-cls class et typename
sont strictement quivalents. Ils permettent simplement de sp-
cifer que le paramtre template est un type (ce qui nest pas
obligatoire). Certains programmeurs prfrent utiliser systma-
tiquement typename plutt que class, car ils trouvent cela plus
clair et conceptuellement plus beau. Dautres, par habitude,
donnent une smantique diffrente ces mots-cls : typename
pour les cas totalement gnriques, comme les conteneurs STL,
et class pour les cas particuliers rservs certaines classes.
Dautres encore utilisent exclusivement class. Vous laurez com-
pris, cest une affaire de choix personnel. Jespre simplement
que ces quelques lignes vous auront permis dy voir plus clair
dans les habitudes de programmation que vous rencontrerez.
Crer une bibliothque
avec des templates
template [class
|
struct] Objet<valeur [, ]>;
Linstanciation explicite complte permet de forcer linstan-
ciation dun template. Cela est particulirement utile
pour les bibliothques : ce faisant, il devient possible de
coupler lintrt des templates et le fait de ne pas livrer
votre implmentation. Par contre, cela peut galement
empcher lutilisateur de ladite bibliothque dutiliser
vos objets templates sur dautres types que ceux que vous
aurez pr-instancis, moins de lui livrer aussi votre
implmentation.
Pour raliser une instanciation explicite, il sufft de pr-
ciser les paramtres templates et de faire prcder ce type
explicit par le mot-cl template. Par exemple, si vous
Lrccr unc hh|oIhcquc avcc dcs Icmp|aIcs
100 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
vouliez forcer linstanciation dun modle Pile pour des
entiers, vous pourriez crire :
template class Pile<int>;
Cette syntaxe peut tre simplife pour les fonctions tem-
plates. Comme pour leur utilisation, il sufft que le compi-
lateur puisse dterminer les types des paramtres utiliss.
Le code template int min(int, int); sufft donc forcer
linstanciation de la fonction min() cite prcdemment.
Lorsquune fonction ou une classe template possde des
valeurs par dfaut pour tous ses paramtres templates, il
nest pas ncessaire de prciser nouveau ces paramtres
correspondants. Par exemple, le code suivant suffrait :
template class MaClasse<>;
Pour une instanciation concernant une bibliothque
dynamique, on utilise conjointement linstanciation expli-
cite et la spcifcation dexportation du code. Pour simpli-
fer lexemple ci-aprs, qui contient trs peu de fchiers,
jai laiss la dclaration du defne de limplmentation dans
le fchier source de la DLL.
#ifdef MADLL_IMPLEMENTATION
#defne MADLL_API __declspec(dllexport)
#else
#defne MADLL_EXPORT __declspec(dllimport)
#endif
template <>
class MADLL_API MaClasse
{
//
MADLL_API Type fonction(parametres);
};
Fichier entte de la bibliothque
101
#defne MADLL_IMPLEMENTATION
#include mon_header.hpp
template <>
MADLL_API Type MaClasse<>::fonction(parametres)
{
//
}
// Instanciations explicites
template class MADLL_API MaClasse<double>;
template class MADLL_API MaClasse<int>;
Fichier source de la bibliothque
#include mon_header.hpp
MaClasse<double> mc_d;
MaClasse<int> mc_i;
MaClasse<foat> mc_f;
//
mc_d.fonction(); // OK
mc_i.fonction(); // OK
mc_f.fonction(); // ERREUR de link : fonction non dfnie
Exemple dutilisation de la bibliothque
Utiliser un type indirect
dans un template
typename identifcateur
Le mot-cl typename rvle tout son intrt dans lutilisation
dun type dfni par une classe ou une structure lorsque cette
uI|scr un Iypc ndrccI dans un Icmp|aIc
102 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
dernire est elle-mme utilise comme paramtre template.
Considrez le code suivant :
class A
{
public:
typedef int Type;
};
template <class T>
class B
{
typename T::Type m_valeur;
};
B<A> b;
Si vous omettez le typename, le code ne compile plus : le
compilateur narrive pas comprendre que T::Type est
bien un type. Et pour cause, il ne sait pas encore quel sera
le type de T.
Changer limplmentation par
dfaut fournie par un template
template<> Type fonction<>() { }
template<> class<> { };
La spcialisation permet de changer limplmentation par
dfaut fournie par un template. Pourquoi ? Le but du tem-
plate est de ne pas dupliquer le code. Mais de ce fait, les
algorithmes implments ainsi sont souvent gnriques,
parfois au dtriment des performances. Cest l quinter-
vient la spcialisation, partielle ou totale, des fonctions,
classes ou membres de classes templates. Ce mcanisme
108
permet, comme son nom lindique, de spcialiser ces tem-
plates pour certains paramtres donns dans le but de
fournir des algorithmes plus performants adapts ces cas
particuliers.
Par exemple, une implmentation gnrique dun mca-
nisme de pile travaillant sur des pointeurs sur objets peut
avoir intrt tre spcialise pour des objets de petite
taille ou des types fondamentaux du langage. En vitant
ainsi un niveau dindirection, les performances peuvent
tre amliores pour ces types.
La spcialisation totale implique de fournir tous les param-
tres templates de la fonction ou de la classe mais de les
omettre dans la dclaration template. Lexemple ci-aprs
montre comment spcialiser la fonction std::min() sur un
type de donnes particulier.
struct Structure
{
int id;
//
};
namespace std
{
template<>
const Structure& min(const Structure& s1,
const Structure& s2)
{
if (s1.id < s2.id)
return s1;
return s2;
}
}
Lhangcr |mp|cmcnIaIon par dcfauI fournc par un Icmp|aIc
104 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
Spcialiser partiellement
limplmentation dun template
template<> Type fonction<>() { }
template<> class<> { };
La spcialisation totale implique la rcriture de tout le
code concern par la spcifcation. Pour les classes, cela
peut vite savrer fastidieux, surtout si vous navez besoin
den spcialiser quune partie. Pour remdier cela, il
existe la spcialisation partielle. Elle peut tre partielle sous
deux aspects :
soit elle ne spcialise quune partie des paramtres tem-
plates ;
soit elle ne spcialise quune mthode de la classe.
Ces deux aspects peuvent tre cumuls lorsquil sagit
dune fonction membre.
La spcialisation partielle des paramtres templates permet
de garder certains paramtres du templates comme indf-
nis. Il est possible de changer la nature dun paramtre
template (passer dun pointeur un non pointeur et vice
versa). Lexemple suivant montre comment faire des sp-
cialisations partielles :
template<int i, class A, class B> class Objet {};
template<int i, class A> class Objet<i,A,A*> {};
template<int i, class A, class B> class Objet<i,A*,B> {};
template<class A> class Objet<2,A,char> {};
Ne vous emballez pas, vous constaterez lusage quil existe
aussi certaines restrictions :
une expression spcialisant un argument template ne doit
pas utiliser un paramtre template de la spcialisation ;
105
template<int I, int J> class Obj {};
template<int K> class Obj<K, 5*K> {}; // ERREUR
le type d'un paramtre spcialisant un argument tem-
plate ne doit pas dpendre d'un paramtre de la spcia-
lisation ;
template<class T, T t> struct Obj {};
template<class T> struct Obj<T, 1> {}; // ERREUR
la liste des arguments de la spcialisation ne doit pas
tre implicitement identique au template d'origine.
template<class A, class B> class Obj {};
template<class B, class A> class Obj<B,A> {}; // ERREUR
Spcialiser une fonction membre
template<> Type Objet<>::methode() { }
template<> Type Objet<>::methode() { }
Le dernier type de spcialisation concerne une mthode
dune classe template. Nul besoin de spcialiser toute une
classe si spcialiser une ou plusieurs mthodes de celle-ci
sufft. La technique est simple : il sufft de faire comme si
la mthode tait une fonction normale et spcialiser les
paramtres templates souhaits. Lexemple suivant vous
rappelle comment :
template <typename T>
class Objet
{
T m_valeur;
Spcca|scr unc foncIon mcmhrc
108 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
public:
Objet(T t)
{
m_valeur = t;
}

void set(T)
{
m_valeur = t;
}

T get() const
{
return m_valeur;
}

void affcher() const
{
std::cout << m_valeur << std::endl;
}
};

// spcialisation dune fonction membre
template <>
void Objet<int*>::print() const
{
cout << *item << endl;
}
Excuter du code la compilation
La mtaprogrammation par templates consiste faire excuter
du code par le compilateur laide des templates. Elle nest
pas lapanage du C++ et se retrouve dans dautres langages
comme Curl, D, Eiffel, Haskell, ML ou XL. Pour tre mise
en uvre en C++, cette technique repose sur deux op-
rations : la dfnition dun template (ou plusieurs) et sa (ou
leurs) instanciation.
101
Certains diront peut-tre que les macros sont aussi excutes
la compilation. Mais les macros ne peuvent effectuer des
contrles de type et manquent de smantique : elles ne sont
quun systme de manipulation et de substitution de texte.
Les mtaprogrammes templates nont, proprement parler,
pas de variables, et ne peuvent manipuler que des constantes.
Les valeurs changent de par la rcursion. La mtaprogramma-
tion peut du coup tre vue comme un langage fonctionnel :
cest en fn de compte une sorte de machine de Turing.
// La mtafonction factorielle
template <int n>
struct Factorielle
{
enum { Result = n * Factorielle<n-1>::Result };
};

// On atteint la fn de la rcursion grce une
// spcialisation partielle
template <>
struct Factorielle<0>
{
enum { Result = 1 };
};

// Lancement du calcul par linstanciation
Factorielle<5>::Result; // vaut 120 la compilation

// Il faut utiliser des constantes uniquement
int i=5;
Factorielle<i>::Result; // ERREUR
const int j=5;
Factorielle<j>::Result; // OK, vaudra 120 la compilation
Les mtafonctions templates peuvent bien entendu tre
utilises pour en construire dautres, comme en program-
mation classique. Lexemple ci-aprs illustre lutilisation de
LxccuIcr du codc a |a comp|aIon
108 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
la mtafonction Factorielle<> pour construire la fonction
mathmatique.
C
i
n
n!
i! (ni)!
=C (n,i) =
Figure 5.1 : Formule factorielle
template <int n, int i>
struct Comb
{
enum
{
Result = Factorielle<n>::Result / ( Factorielle

<i>::Result * Factorielle<n-i>::Result)
};
};
//
Comb<5,3>::Result;
Crer des mta-oprateurs/
mtabranchements
template <bool g, class THEN, class ELSE>
struct IF
{
typedef THEN Result;
};
template <class THEN, class ELSE>
struct IF<false, THEN, ELSE>
{
typedef ELSE Result;
};
100
La mtaprogrammation template peut mme utiliser des
tests conditionnels du type if then else Cela est
certes moins lisible mais fonctionne parfaitement. Le code
suivant montre comment utiliser ce genre de mtaopra-
teurs :
class Allocateur1 {};
class Allocateur2 {};

IF <UseAllocatorNumber==1,
Allocateur1, // THEN type
Allocateur2> // ELSE type
::Result allocator;
De la mme manire, il est possible de faire comme si lon
disposait de valeurs boolennes. Le code ci-aprs illustre
comment les simuler. Pour cela, nous rutilisons lexemple
prcdant en adaptant la mtaclasse de test IF, et lui adjoi-
gnions deux classes FAUX et VRAI qui feront offce de valeurs
boolennes. Ensuite, la mtaclasse isPointer<> permet de
dterminer si son paramtre template est ou non de type
pointeur en renvoyant VRAI ou FAUX. Ce rsultat peut enfn
tre utilis lors dun test IF.
struct FAUX {};
struct VRAI {};
template <class BOOL, class THEN, class ELSE>
struct IF
{
typedef THEN Result;
};
template <class THEN, class ELSE>
struct IF<FAUX, THEN, ELSE>
{
typedef ELSE Result;
};
template <class T> struct isPointer { typedef FAUX Result; };
Lrccr dcs mcIa-opcraIcursjmcIahranchcmcnIs
110 LhAPIJL 5 Jcmp|aIcs cI mcIaprogrammaIon
template <class T> struct isPointer<T*> { typedef VRAI

Result; };

template <class T>
class MonTableau
{
IF< isPointeur<T>::Result, T, T*>::Result

type_interne;
//
};
Si vous testez ce dernier exemple, vous remarquerez cer-
tainement que votre compilateur naccepte pas le IF<>
prsent dans la classe MonTableau. Cela est frustrant, mais
vous montre les limites de linterprtation des templates
par le compilateur. Cest pour cette raison, entre autre, que
les types traits ou dautres biais sont utiliss.
LurosIc
Aprs les macros, aprs les fonctions inline, aprs les templa-
tes, voici la version mtaprogramme des fonction min() et
max(). Encore ? Quel intrt ? Deux raisons cette curiosit :
elles illustrent un aspect supplmentaire de la mtaprogram-
mation et pourront vous tre utiles pour mtaprogrammer .
Voici donc une implmentation possible de ces dernires pour
des entiers :
template <int a, int b> struct Min { enum { Result =

(a < b) ? a : b; }; };
template <int a, int b> struct Max { enum { Result =

(a > b) ? a : b; }; };

111
Avantages et inconvnients
de la mtaprogrammation
Compromis entre temps de compilation et temps
d'excution. Tout code template est analys, valu et
dploy pendant la compilation. Elle peut donc pren-
dre beaucoup de temps mais cela permet dobtenir un
code trs rapide lexcution. Ce surcot est gnrale-
ment faible mais peut devenir non ngligeable pour de
gros projets ou des projets utilisant intensment la
mtaprogrammation template.
Programmation gnrique. La mtaprogrammation
template permet de se concentrer sur larchitecture
tout en laissant au compilateur la charge de gnrer le
code ncessaire. La mtaprogrammation fournit donc
un moyen dcrire du code gnrique et dcrire moins
de code. La maintenance du code en est facilite.
Lisibilit. En mtaprogrammation C++, la syntaxe et
les idiomes du langage sont souvent ardus lire par
rapport du C++ classique. Ce code peut mme rapi-
dement devenir trs diffcile dchiffrer. Un trs bon
niveau et surtout beaucoup dexprience peuvent
devenir indispensables. La maintenance dun tel code,
qui est cense tre facilite, peut sen trouver rserve
un petit nombre de programmeurs qualifs.
Portabilit. Tous les compilateurs ne se valent pas.
Surtout en ce qui concerne lvaluation des templates.
Un code reposant massivement sur cette notion peut
devenir trs diffcile porter, voir impossible si vous ne
disposez pas dun compilateur rcent.
AvanIagcs cI nconvcncnIs dc |a mcIaprogrammaIon
6
0csIon dc |a
mcmorc
Rserver et librer la mmoire
Type* variable = new Type;
delete variable
double* variable = new double[n];
delete [] variable;
linstar de la fonction malloc(), loprateur new permet
dallouer dynamiquement de la mmoire. Notez toutefois
quinvoquer new provoquera linitialisation des donnes
dun objet laide de son constructeur, sil existe. new Type
alloue un objet, tandis que new Type[n] alloue un tableau
de n objets contigus.
114 LhAPIJL 8 0csIon dc |a mcmorc
AIIcnIon
Utiliser delete au lieu de delete[], ou inversement, peut
entraner un comportement imprvisible de votre application.
Dune manire gnrale, utilisez delete pour un new et
delete[] pour un new[].
Faites toutefois trs attention : dans certains cas, il nest pas
toujours facile de dterminer lequel utiliser. Pour bien com-
prendre la rgle prsente, examinez cet exemple :
struct Livre { };
typedef Bibliotheque Livre[8];
Livre* livre = new Livre;
//Bibliotheque *biblio = new Bibliotheque; => ERREUR
Livre* biblio = new Bibliotheque; // OK
delete livre;
// delete biblio; => ERREUR : comportement imprvisible
delete[] biblio; // OK
Si vous avez compris le principe, vous aurez remarqu que le
new Bibliotheque est en fait un new Livre[8] cach qui
ncessite bien une destruction par delete[].
Redfnir le systme dallocation
mmoire
void* operator new(size_t size);
void* operator new[](size_t size)
operator delete(void* ptr);
operator delete[](void *ptr);
115
Vous pouvez redfnir votre propre systme dallocation
mmoire en redfnissant les oprateurs globaux new et
delete. Vous pouvez ainsi optimiser lallocation mmoire
de toute une application en utilisant un ou plusieurs pools
de mmoire, ou utiliser des ressources systme particuli-
res de manire transparente pour le reste de votre code.
AIIcnIon
Redfnir ces oprateurs globaux aura un effet sur toutes les
allocations de votre programme.
Dautres solutions existent si vous souhaitez optimiser lal-
location mmoire de vos programmes :
loprateur de placement ;
une surcharge des oprateurs new et delete au niveau de
vos classes ;
la technique des allocateurs (elle est largement utilise
au sein de la STL).
Simuler une allocation dobjet
une adresse connue
new(adresse) Type
new(adresse) Type[n]
Les oprateurs de placement simulent une allocation
dobjet une adresse connue. Ces oprateurs ne font que
renvoyer ladresse fournie.
Smu|cr unc a||ocaIon doh|cI a unc adrcssc connuc
118 LhAPIJL 8 0csIon dc |a mcmorc
AIIcnIon
Vous ne devez jamais utiliser delete sur des objets ainsi crs.
Au besoin, appelez explicitement le destructeur pour appliquer
les traitements qui y sont associs :
Obj* o = new(&quelqueChose) Obj;
//
o->~Obj(); // appel explicite du destructeur sans

dtruire lobjet lui-mme


Info
Cet oprateur utilise la mme technique de surcharge que
loprateur new sans exception (voir la section suivante).
Traiter un chec de rservation
mmoire
try
{
Type *objet = new Objet;
}
catch (std::bad_alloc)
{
//
}
Un chec dallocation mmoire se traduit par le lance-
ment de lexception std::bad_alloc. Si vous souhaitez que
votre application ne se termine pas inopinment, vous
avez intrt traiter un tel cas derreur en capturant cette
dernire. Vous pourrez ainsi lancer un message derreur ou
lancer un systme de rcupration de mmoire (comme
un systme de sauvegarde, libration, traitement, ralloca-
tion de la sauvegarde) votre gr.
111
Une autre technique pour intercepter un chec dalloca-
tion consiste mettre en place un handler ddi. Lorsque
celui-ci se termine normalement, loprateur new tente
une nouvelle allocation. Si celle-ci choue nouveau, le
handler est nouveau invoqu. Voici quoi pourrait res-
sembler un tel handler :
#include <iostream>
#include <new>
#include <exception>
using namespace std;

void newHandlerPerso()
{
static int numEssai = 0;
switch( numEssai )
{
case 0:
// compacter le tas
std::cout << Compacter le tas\n;
numEssai++;
break;
case 1:
// nettoyer la mmoire du code inutile
std::cout << nettoyer la mmoire du code inutile\n;
numEssai++;
break;
case 2:
// utiliser un fchier swap
std::cout << utiliser un fchier swap\n;
numEssai++;
break;
default:
std::cerr << Pas assez de mmoire\n;
numEssai++;
throw std::bad_alloc();
}
}
JraIcr un cchcc dc rcscrvaIon mcmorc
118 LhAPIJL 8 0csIon dc |a mcmorc
Vous pourrez activer ce handler volont ainsi :
typedef void (*handler)();
handler ancienHandler = 0;
void test_handler()
{
handler ancienHandler =

set_new_handler( newHandlerPerso );
// code protg
try
{
while ( 1 )
{
new int[5000000];
cout << Allocation de 5000000 ints. << endl;
}
}
catch ( exception e )
{
cout << e.what( ) << xxx << endl;
}
//
set_new_handler( ancienHandler );
}
int main(int,char**)
{
test_handler();
return 0;
}
110
Dsactiver le systme
dexception lors de lallocation
#include <new>
Type *obj = new(std::nothrow) Type;
int *a = new(std::nothrow) int[1000000000];
Le fchier den-tte standard <new> dfnit une structure
appele std::nothrow_t dans lespace de nom std. Cette
structure vide sert de directive en forant lappel de new
tre redirig sur ces surcharges des oprateurs :
void* operator new(size_t size, const std::nothrow_t&);
void* operator new(void* v, const std::nothrow_t& nt)
Dclaration apparaissant dans <new>
<new> dfnit galement une instance extern const nothrow_t
nothrow; permettant dutiliser de manire uniforme ladite
syntaxe.
Objet* objets = new(std::nothrow) Objet[1000000000];
if (objets == 0)
{
std::cout << Erreur allocation memoire << std::endl;
}
0csacIvcr |c sysIcmc dcxccpIon |ors dc |a||ocaIon
120 LhAPIJL 8 0csIon dc |a mcmorc
Optimiser lallocation
avec un pool mmoire
boost::pool<> pool(tailleEnOctets);
boost::object_pool<Type> pool;
boost::singleton_pool<PoolTag, TailleEnOctets> pool;
boost::pool_allocator<Type>
Plutt que de dvelopper vous-mme un systme de pools
(ou bacs) de mmoire, utilisez ceux fournis par BOOST.
Pour en savoir plus sur cet ensemble de bibliothques,
reportez-vous au Chapitre 13, consacr BOOST.
Pour les pools de type objet, dtruire le pool libre impli-
citement tous les blocs mmoire allous par celui-ci. Pour
les pools de type singleton, les blocs mmoire ont une
dure de vie gale au programme. Ils peuvent donc tre
aisment partags. Du coup, ils ont t cods pour tre
threadsafe (avec pour corollaire un cot lexcution).
Pour librer les ressources mmoire dun pool de type sin-
gleton, il faut linstancier avec les fonctions membres
release_memory() ou purge_memory().
purge_memory() libre tous les blocs mmoire allous.
release_memory() libre tous les blocs internes non utiliss.
AIIcnIon
Certaines implmentations prfrent retourner 0 (NULL) plutt
que de dclencher une exception lorsquil ny a plus de
mmoire. Soyez donc bien attentif ce point lors de leur uti-
lisation.
Les boost::pool<> sont de type objet et retournent NULL
en cas dchec de rservation mmoire. Dans lexemple
121
ci-aprs, nul besoin de se proccuper de la dsallocation
mmoire, puisque le pool sen chargera lors de sa destruc-
tion la fn de la fonction.
#include <boost/pool/pool.hpp>
void fonction()
{
boost::pool<> p(sizeof(int));
for (int i=0; i < 100000; ++i)
{
int* const i_ptr = (int*)p.malloc();
//
}
}
Les boost::object_pool<> sont de type objet et retournent
NULL en cas dchec dallocation mmoire. Ils tiennent
compte du type dobjet allou. L encore, tous les objets
concerns sont dtruits avec le pool.
#include <boost/pool/object_pool.hpp>
class Objet { };
void fonction()
{
boost::object_pool<Objet> p;
for (int i=0; i < 100000; ++i)
{
Objet* const i_ptr = p.malloc();
//
}
}
Les boost::singleton_pool sont de type singleton. Ils
retournent NULL en cas dchec dallocation mmoire
(encore). Par contre, la mmoire nest libre quexplicite-
ment. Le tag permet de crer plusieurs instances diffren-
tes de ce pool de mmoire.
0pImscr |a||ocaIon avcc un poo| mcmorc
122 LhAPIJL 8 0csIon dc |a mcmorc
#include <boost/pool/singleton_pool.hpp>
struct MonPool_Tag{};
typedef boost::singleton_pool<MonPool_Tag,
sizeof(int)> MonPool;
void fonction()
{
for (int i=0; i < 100000; ++i)
{
int* const i_ptr = (int*)MonPool::malloc();
//
}
// Appel explicite pour librer la mmoire
MonPool::purge_memory();
}
Les boost::pool_alloc sont de type singleton. Attention,
ceux-ci dclenchent une exception en cas dchec dallo-
cation mmoire. Ils sont conus sur les boost:singleton_pool
et sont compatibles avec les allocateurs STL. Dans lexemple
ci-aprs, la mmoire ne sera pas libre la fn de la fonction.
Pour le forcer, il faut appeler boost::singleton_pool<boos::
pool_allocator_tag, sizeof(int)>::release_memory().
#include <boost/pool/pool_alloc.hpp>
#include <vector>
void fonction()
{
std::vector<int, boost::pool_allocator<int> > V;
for (int i=0; i < 100000, ++i)
V.push_back(33);
}
7
LxccpIons
Obtenir un code fable est certainement une des grandes
proccupations des programmeurs. De manire gnrale,
deux possibilits de gestion des erreurs existent : lutilisa-
tion de codes de retour ou les exceptions. Libre vous
dutiliser lune ou lautre de ces possibilits. Ce chapitre
vous permettra dapprhender de manire sereine les
exceptions en C++ afn de les utiliser judicieusement.
Principe
#include <exception>
#include <stdexcept>
try
{
// code pouvant dclencher directement
// ou indirectement une exception
}
catch(type1)
{
// code du gestionnaire traitant les exceptions
// correspondant au type1
}
catch(type2)
124 LhAPIJL 1 LxccpIons
{
// code du gestionnaire traitant les exceptions
// correspondant au type2 (et non traites par un
// des gestionnaires prcdents)
}
//
catch(...)
{
// code du gestionnaire traitant toute exception
// non gre par un des gestionnaires prcdents
}
throw expression;
Les exceptions permettent une forme de communication
directe entre les fonctions bas niveau et les fonctions haut
niveau qui les utilisent. Lutilit de cette communication
est dautant plus vidente lorsque la diffrence de niveau
entre le dclencheur et le gestionnaire est importante. Le
principe est le suivant.
Une fonction dtecte un comportement exceptionnel et
dclenche une exception laide de throw expression.
Lexception est construite grce lexpression fournie
linstruction throw. Elle peut tre un nombre entier ou
fottant, une chane ou un objet. Le plus souvent, il sagit
dun objet dont la classe drive de std::exception, conte-
nant les informations relatives aux caractristiques de
lvnement survenu.
Lexception stoppe le fonctionnement normal du pro-
gramme. Elle dtruit tous les objets construits localement
en remontant bloc par bloc, fonction par fonction (dans la
pile dappel) jusqu rencontrer un gestionnaire (catch)
qui la gre. Si aucun gestionnaire appropri nest trouv,
125
la fonction terminate() est appele ; elle provoque la fn
du programme. Si un gestionnaire est utilis, le programme
poursuit son cours normal linstruction qui suit le der-
nier gestionnaire de son groupe de catch.
Info
La destruction des objets locaux est un des principes fonda-
mentaux les plus utiles du systme des exceptions en C++.
Voici un exemple simple montrant comment garantir que
lon naccde pas un lment en dehors des limites dun
tableau :
class Tableau3
{
int valeur[3];
public:
int get(int i) const
{
if (i<0
||
i>3)
throw std::out_of_range();
return valeur[i];
}
//
};
//
int v = tab.get(4);
Sc|ccIon du gcsIonnarc dc |cxccpIon
Le premier gestionnaire ligible, cest--dire dont le type est
compatible avec lexception, est utilis. Le test dligibilit
dun gestionnaire catch est soumis des rgles de conversion
proche de celles de la surcharge de fonction (voir le Chapitre 2,
section Surcharge ).
Prncpc
128 LhAPIJL 1 LxccpIons
Un gestionnaire catch(T), catch(const T), catch(T&) ou catch
(const T&) est compatible avec une exception de type E si :
T et E dsignent le mme type ou ;
T est une classe de base visible (accessible) de E ou ;
T et E sont des types pointeurs et E peut tre converti
en T par une conversion standard.
Contrairement la surcharge de fonction, si T et E ne sont pas
de type pointeur, aucune conversion standard nest tente.
Voici un exemple :
#include <stdexcept>
//
try
{
throw std::bad_alloc();
}
catch(std::exception& e)
{
// ce gestionnaire correspond lexception

dclenche
// car std::bad_alloc hrite de std::exception.
}
catch(std::bad_alloc&)
{
// jamais atteint,
// car le gestionnaire prcdent est utilis.
}
Notez quun bon compilateur vous signalera votre tourderie
(g++ le fait), par un message de ce type :
excep.cpp: In function `int f(bool):
excep.cpp:22: warning: exception of type

std::bad_alloc will be caught


excep.cpp:13: warning: by earlier handler for
std::exception

121
AIIcnIon
Les dbogueurs modernes permettent de sarrter automatique-
ment sur le dclenchement dune exception. Souvent, cela
permet de trouver trs rapidement lendroit dun bogue.
Toutefois, si votre programme fait un usage abusif des excep-
tions, le dbogueur se mettra trs souvent en pause, rendant la
recherche du bogue au mieux fastidieuse, au pire impraticable.
Peut-tre alors tenterez-vous dutiliser loption Sarrter sur
les exceptions non gres . Mais si votre programme met en
uvre des gestionnaires trs gnriques, le dbogueur ne
sarrtera jamais sur le lieu du bogue.
Vous laurez compris : nutilisez pas abusivement le mcanisme des
exceptions comme systme de traitement derreur normale !
Comme son nom lindique, une exception doit rester une exception !
Il est prudent de ne les utiliser que pour les rels cas danomalies.
AIIcnIon
Lappel dun gestionnaire catch est trait comme un appel de
fonction. Il commence donc, selon le type de paramtre transmis,
par faire une copie de largument ! Soyez donc vigilants et prenez
plutt lhabitude de dclarer le type par rfrence, surtout avec les
objets. Par exemple utilisez catch(const MonException&) plutt
que catch(MonException).
Transmettre une exception
throw;
Dans un gestionnaire catch, vous pouvez utiliser throw; pour
redclencher lexception en cours de traitement comme si
elle navait pas t attrape. Le code qui pourrait suivre cette
instruction dans ledit gestionnaire ne sera pas excut.
JransmcIIrc unc cxccpIon
128 LhAPIJL 1 LxccpIons
Le programme suivant illustre le comportement de la
transmission dexception :
#include <stdexcept>
#include <iostream>

int f(bool transmettre)
{

try
{
throw std::bad_alloc();
}
catch(std::exception& e)
{
// ce gestionnaire correspond lexception

dclenche
// car std::bad_alloc hrite de std::exception.
std::cout << traitement 1 << std::endl;
if (transmettre)
throw;
std::cout << traitement 1 bis << std::endl;
}
catch(std::bad_alloc&)
{
// jamais atteint,
// car le gestionnaire prcdent est utilis.
std::cout << traitement 2 << std::endl;
}
}

int main(void)
{
std::cout << --- essai A --- << std::endl;
try
{
f(false);
}
catch(...)
{
std::cout << traitement 3 << std::endl;
}

120
std::cout << --- essai B --- << std::endl;
try
{
f(true);
}
catch(...)
{
std::cout << traitement 3 << std::endl;
}

return 0;
}
Il produit la sortie suivante :
--- essai A ---
traitement 1
traitement 1 bis
--- essai B ---
traitement 1
traitement 3
Expliciter les exceptions
type fonction(parametres) throw(T,)
type fonction(parametres) throw()
Lexplicitation des types dexceptions (ou exceptions
compatibles) pouvant tre dclenches par une fonction ne
fait pas partie de sa signature. Elle permet nanmoins au
compilateur de faire certaines vrifcations et de vous mettre
en garde par des messages (le plus souvent des warnings).
Lxp|cIcr |cs cxccpIons
180 LhAPIJL 1 LxccpIons
#include <stdexcept>
#include <iostream>

void excep_bad_cast()
{
throw std::bad_cast();
}
void excep_range_error()
{
throw std::range_error(std::string(toto));
}

int f(bool transmettre) throw(std::range_error,

std::bad_alloc)
{
try
{
// dcommenter au choix pour les tests
// excep_bad_cast();
// excep_range_error();
throw std::bad_alloc();
}
catch(std::bad_alloc&)
{
std::cout << traitement 2 << std::endl;
throw;
}
}

int main(void)
{
std::cout << --- essai A --- << std::endl;
try
{
f(false);
}
catch(...)
{
std::cout << traitement 3 << std::endl;
}

return 0;
}
181
En dcommentant la ligne excep_bad_cast(); vous obtien-
drez (avec g++) :
--- essai A ---
terminate called after throwing an instance of

std::bad_cast
what(): St8bad_cast
Abort trap
En dcommentant la ligne excep_range_error(); vous
obtiendrez (avec g++) :
--- essai A ---
traitement 3
Utiliser ses propres
implmentations des fonctions
terminate() et unexpected()
typedef void (*handler)();
handler set_terminate(handler);
handler set_unexpected(handler);
Vous pouvez utiliser vos propres implmentations des
fonctions terminate() et unexpected(). Elles retournent le
handler en vigueur avant lappel. vous de le sauvegarder
pour ventuellement le remettre.
uI|scr scs proprcs mp|cmcnIaIons dcs foncIons terminate() cI unexpected()
182 LhAPIJL 1 LxccpIons
AIIcnIon
Votre fonction terminate() doit imprativement terminer le
programme en cours. Elle ne doit ni retourner lappelant, ni
lancer une quelconque exception.
Votre fonction unexpected() peut ne pas terminer le pro-
gramme. Dans ce cas, elle doit imprativement dclencher une
nouvelle exception.
Lexemple suivant montre comment mettre en place vos
propres gestionnaires :
void my_stop()
{
QMessageBox::critical(0,Erreur irrcuprable,
Lapplication a rencontr une erreur

inattendue
et va se fermer);
exit(-1);
}
void fonction()
{
std::terminate_handler orignal =

set_terminate(my_stop);
//
set_terminate(original);
}
Utiliser les exceptions
pour la gestion des ressources
Considrez par exemple un code effectuant les oprations
suivantes :
1. Rserver une ressource.
2. Faire un traitement.
3. Librer la ressource.
188
Ce type de code peut paratre anodin et sans danger. Et
pourtant que se passerait-il si le traitement devait dclen-
cher une exception ? Votre ressource ne serait jamais lib-
re. Vous pourriez alors opter pour cette solution :
try
{
reserver_ressource();
traitement();
}
catch(...)
{
liberer_ressource();
}
Cette solution peut tre viable, mais devient vite imprati-
cable dans certaines situations. Considrez le cas de plu-
sieurs rservation/traitement avec une libration du tout
la fn, ou bien plusieurs rservations suivies dun traite-
ment pour enfn librer toutes vos ressources Vous ren-
contrerez ce cas rgulirement avec les allocations mmoire.
Que se passerait-il en utilisant la mthode prcdente ?
try
{
ObjetA * objetA = new ObjetA();
ObjetB * objetB = new ObjetB();
// traitement
}
catch(...)
{
delete objetA;
delete objetB;
}
Si une exception bad_alloc est dclenche lors de lalloca-
tion de lobjetB, linstruction delete objetB aura un com-
portement imprvisible ! Mme un test sur la valeur du
pointeur nest pas suffsant.
uI|scr |cs cxccpIons pour |a gcsIon dcs rcssourccs
184 LhAPIJL 1 LxccpIons
AsIucc
Utilisez des objets pour allouer des ressources et non des poin-
teurs.
Voici une version simpliste de std::auto_ptr pouvant servir
de modle pour rsoudre tous vos problmes :
template<class T>
struct Ptr
{
Ptr(T* p) : ptr(p) {}
~Ptr() { delete p; }
T* get() const { return ptr; }
T* operator->() const { return ptr; }
private:
T* ptr;
};
Le code prcdent devient alors non seulement plus simple,
mais totalement sr. En effet, si la deuxime allocation choue,
le deuxime objet ne sera pas cr et son destructeur ne sera
pas appel. Par contre, de par le fonctionnement du C++, nous
avons la garantie que le premier sera bien dtruit, provoquant
la libration de la ressource alloue.
Ptr<Objet> ptrA(new ObjetA());
Ptr<ObjetB> ptrB(new ObjetB());
// traitement identique

Exceptions de la STL
Vous trouverez dans le tableau suivant toutes les exceptions
utilises (ou qui le seront dans de prochaines volutions) par
la STL.
185
<exception> (inclus par <stdexcept>)
Jypc 0cscrpIon
exception Classe de base de toutes les exceptions pouvant
tre dclenches par la bibliothque STL ou
certaines expressions du langage C++. Vous
pouvez dfnir vos propres exceptions en hritant
de celle-ci si vous le souhaitez.
+ bad_exception Peut tre dclenche si une exception
non rpertorie dans la liste des exceptions
autorises par une fonction est dclenche
<stdexcept>
Jypc 0cscrpIon
+ logic_error Reprsente les problmes de logique interne au
programme. En thorie, ils sont prvisibles et
peuvent souvent tre reprs par une lecture
attentive du code (comme par exemple lors de
la violation dun invariant de classe).
+ + domain_error Dclenche par la bibliothque, ou par vous,
pour signaler des erreurs de domaine (au sens
mathmatique du terme)
+ + invalid_argument Dclenche pour signaler le passage
dargument(s) invalide(s) une fonction
+ + length_error Dclenche lors de la construction dun
objet dpassant une taille limite autorise.
Cest le cas de certaines implmentations
de basic_string.
+ + out_of_range Dclenche lorsquune valeur dun
argument nest pas dans les limites (bornes)
attendues. La mthode at() des vector
effectue un test de borne et dclenche cette
exception si besoin.
+ runtime_error Reprsente les problmes sortant du cadre
du programme. Ces problmes sont
diffcilement prvisibles et surviennent
lors de lexcution du programme.
+ + range_error Dclenche pour signaler une erreur de
borne issue dun calcul interne
LxccpIons dc |a SJL
188 LhAPIJL 1 LxccpIons
<stdexcept> (suite)
Jypc 0cscrpIon
+ + overfow_error Dclenche pour signaler un dbordement
arithmtique (par le haut)
+ + underfow_error Dclenche pour signaler un dbordement
arithmtique (par le bas)
<type_info>
Jypc 0cscrpIon
+ bad_cast Dclenche lors dune conversion dynamique
dynamic_cast invalide
+ bad_typedid Dclenche si un pointeur nul est transmis
une expression typeid()
<new>
Jypc 0cscrpIon
+ bad_alloc Dclenche par new (dans sa forme standard,
cest--dire sans le nothrow) pour signaler un
chec dallocation mmoire
Info
Aucune exception ne peut (et ne doit, si vous crivez vos pro-
pres classes en hritant de exception) dclencher pendant
lexcution dune fonction membre de la classe exception.
AsIucc
La classe de base exception possde une fonction virtuelle
const char* what() qui retourne une chane de caractres la
dcrivant .
8
IIcraIcurs
Les itrateurs sont une gnralisation des pointeurs. Notez
que je ne parle pas ici de LA gnralisation, mais bien
dUNE gnralisation. Dautres types de gnralisation
des pointeurs existent, comme la notion de pointeur fort/
pointeur faible.
Un itrateur est une interface standardise permettant de
parcourir (ou itrer) tous les lments dun conteneur. Les
itrateurs prsentent la mme smantique que les poin-
teurs par plusieurs aspects :
ils servent dintermdiaire pour atteindre un objet
donn ;
si un itrateur pointe sur un lment donn dun
ensemble, il est possible de lincrmenter pour quil
pointe alors sur llment suivant.
Les itrateurs sont un des lments essentiels la program-
mation gnrique. Ils font le lien entre les conteneurs et
les algorithmes. Ils permettent dcrire un algorithme de
manire unique quel que soit le conteneur utilis, pourvu
que ce dernier fournisse un moyen daccder ses l-
ments travers un itrateur. Vous aurez certainement dj
compris que ce qui importe pour lalgorithme nest plus
de savoir sur quel type de conteneur mais sur quel type
ditrateur il travaille.
188 LhAPIJL 8 IIcraIcurs
Il est donc possible et mme ncessaire davoir plusieurs
(ou suffsamment) catgories ditrateurs si lon veut pou-
voir crire un large ventail dalgorithmes gnriques.
Rassurez-vous, la bibliothque standard (STL) vous a
mch le travail en dfnissant plusieurs itrateurs, et mme
mieux, une hirarchie ditrateurs.
Les diffrents concepts
Les itrateurs sont utiliss pour accder aux membres des
classes conteneurs de la STL. Ils peuvent tre utiliss dune
manire analogue aux pointeurs. Par exemple, il est possi-
ble dutiliser un itrateur pour parcourir les lments dun
std::vector. Il existe plusieurs types ditrateurs. Vous les
retrouverez dans le tableau ci-aprs. Plus que des types, ce
sont surtout des concepts.
Les diffrents itrateurs STL
Jypc 0cscrpIon
InputIterator Lire des valeurs en avanant. Ils peuvent tre
incrments, compars et drfrencs.
OuputIterator crire des valeurs en avanant. Ils peuvent tre
incrments et drfrencs.
ForwardIterator Lire et/ou crire des valeurs en avanant. Ils
combinent les fonctionnalits des InputIterator et
des OutputIterator avec la possibilit de stocker les
itrateurs eux-mmes.
BidirectionalIterator Lire et/ou crire des valeurs en avanant et/ou en
reculant. Ils sont comme les ForwardIterator mais ils
peuvent tre incrments et/ou dcrments.
180
Jypc 0cscrpIon
RandomAccessIterator Lire et/ou crire des valeurs dans un ordre alatoire.
Alatoire ne signife pas ici au hasard mais dans
nimporte quel ordre, selon vos besoins. On le
traduit parfois par itrateur daccs direct . Ce sont
les itrateurs les plus puissants ; ils ajoutent aux
fonctionnalits des BidirectionalOperator les possibilits
deffectuer des oprations semblables larithm-
tique des pointeurs et la comparaison des pointeurs.
Chaque classe conteneur de la STL est associe un type
ou concept ditrateur. Il en est de mme pour tous les
algorithmes fournis par la STL : chacun utilise un type
ditrateur particulier. Par exemple, les vecteurs (std::
vector) sont associs aux RandomAccessIterator (itrateur
accs alatoire). Il en dcoule quils peuvent tre utiliss
avec tous les algorithmes bass sur ce type ditrateur.
Comme cet itrateur englobe toutes les caractristiques
des autres types ditrateurs, les vecteurs peuvent aussi tre
utiliss avec tous les algorithmes conus pour les autres
types ditrateurs.
Le code suivant cre et utilise un itrateur avec un vecteur :
std::vector<int> V;
std::vector<int>::iterator iterateur;
for (int i=0; i<10; i++)
V.push_back(i);
int total = 0;
for (iterateur = V.begin(); iterateur != V.end();
iterateur++)
total += *iterateur;
std::cout << Total = << total << std::endl;
Notez que vous pouvez accder aux lments du conte-
neur en drfrenant litrateur.
Lcs dffcrcnIs conccpIs
140 LhAPIJL 8 IIcraIcurs
Comprendre les iterator_traits
#include <iterator>
template <class Iterator>
struct iterator_traits
{
typedef typename Iterator::iterator_category

iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference

_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};

template <class T>
struct iterator_traits<T*>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
Une des caractristiques les plus importantes des itrateurs
est davoir des types associs. un type ditrateur est
donc associ dautres types, comme :
value_type. Le type de valeur est le type dobjet sur
lequel litrateur pointe.
difference_type. Le type de distance (ou type de la dif-
frence) entre deux itrateurs. Ce peut tre un type
intgral comme int.
Les pointeurs, par exemple, sont des itrateurs. Par exemple,
le type de valeur de int* est int. Le type de distance est
ptrdiff_t puisque si p1 et p2 sont des pointeurs, lexpression
p1 p2 est de type ptrdiff_t.
141
Les algorithmes gnriques ont souvent besoin daccder
des types associs. Un algorithme qui prend en paramtre une
squence ditrateurs peut avoir besoin de dclarer une varia-
ble temporaire du type de la valeur pointe. La classe itera-
tor_traits fournit un mcanisme pour de telles dclarations.
Une technique de prime abord vidente pour une telle
fonctionnalit serait dimposer tous les itrateurs dembar-
quer ces dclarations de type. Ainsi, le type de valeur dun
itrateur I serait I::value_type. Nanmoins, cela ne fonc-
tionne pas bien. Les pointeurs sont des itrateurs et ne sont
pas des classes : si I tait, par exemple, un int*, il serait
impossible de dfnir I::value_type. Le concept de traits
template a t cr pour remdier ce genre de diffcults.
Info
Une classe de caractristiques ou traits class est une classe uti-
lise en lieu et place de paramtres templates. Elle embarque
des constantes et types utiles. Elle offre un nouveau niveau
dindirection pour rsoudre de nombreux problmes. lorigine,
ce concept portait le nom de bagage ou valise (baggage)
contenant des caractristiques (traits) et a fni par tre appel
directement traits.
Si vous dfnissez un nouvel itrateur I, vous devez vous
assurer que iterator_traits<I> soit correctement dfni.
Vous avez deux possibilits pour cela. Premirement, vous
dfnissez votre itrateur de telle sorte quil contienne les
types associs I::valu_type, I::difference_type et ainsi de
suite. Deuximement, vous pouvez spcialiser iterator_
traits avec votre type. La premire technique est la plupart
du temps plus pratique, surtout lorsque vous pouvez crer
votre itrateur en hritant dune des classes de base input_
iterator, output_iterator, forward_iterator, bidirectio-
nal_iterator, ou random_access_iterator.
Lomprcndrc |cs iterator_traits
142 LhAPIJL 8 IIcraIcurs
Lexemple suivant illustre lutilisation de cette classe traits :
template <class InputIterator>
std::iterator_traits<InputIterator>::value_type
derniere_valeur(InputIterator debut, InputIterator fn)
{
std::iterator_traits<InputIterator>::value_type

resultat = *debut;
for (++debut; debut != fn ; ++debut)
resultat = *debut;
return resultat;
}
Cette fonction renvoie la valeur du dernier lment dune
squence. Bien videmment, ce nest pas un exemple de
bon code. Il existe de bien meilleures faons darriver
au mme rsultat, surtout si litrateur est du type bidirec-
tional_iterator ou forward_iterator. Mais vous pouvez
noter quutiliser les iterator_traits est le seul moyen
dcrire une fonction gnrique de ce type.
Calculer la distance
entre deux itrateurs
#include <iterator>
iterator_traits<InputIterator>::difference_type
distance(InputIterator debut, InputIterator fn);
void distance(InputIterator debut, InputIterator

fn, Distance& n);


Ces fonctions retournent la distance d entre debut et fn,
autrement dit debut doit tre incrment d fois pour quil
devienne gal fn. La premire version de distance()
retourne cette distance, la deuxime lajoute au n donn.
148
Info
La deuxime version de distance() a t dfnie dans la STL
originale, et la premire version a t introduite par le comit
de standardisation C++. La dfnition a t modife car lan-
cienne tait source derreur. En effet, cette version requrait
lutilisation dune variable temporaire et son utilisation ntait
pas intuitive : elle ajoutait n la distance entre debut et fn
plutt que simplement lui affecter cette valeur. Du coup,
oublier dinitialiser n zro tait une erreur rpandue.
Bien entendu, les deux versions sont implmentes par souci
de compatibilit, mais vous tes encourag toujours utiliser
la version du comit (et qui renvoie la distance).
Lexemple ci-aprs montre que la fonction distance()
fonctionne mme avec les conteneurs accs squentiel
(au sens propre du terme), mais alors sa complexit est
linaire et plus en temps constant. Vous devez donc lutili-
ser en connaissance de cause.
std::list<int> L;
L.push_back(0);
L.push_back(1);
assert(std::distance(L.begin(), L.end()) == L.size());
AIIcnIon
Si votre compilateur ne supporte pas la spcialisation partielle
(voir la section Spcialiser partiellement limplmentation
dun template au Chapitre 5), vous ne pourrez pas utiliser les
fonctions utilisant std::iterator_traits<>. Cette classe repose
en effet largement sur cette spcifcit du langage C++.
Rassurez-vous, la plupart des compilateurs modernes suppor-
tent la spcialisation partielle.
La|cu|cr |a dsIancc cnIrc dcux IcraIcurs
144 LhAPIJL 8 IIcraIcurs
Dplacer un itrateur
vers une autre position
#include <iterator>
void advance(InputIterator& i, Distance n);
advance() incrmente i de la distance n. Si n est positif,
cela est quivalent excuter n fois ++i, et sil est ngatif
|
n
|
fois --i. Si n est nul, la fonction na aucun effet.
Lexemple suivant illustre lutilisation de cette fonction sur
les listes :
std::list<int> L;
L.push_back(0);
L.push_back(1);
std::list<int>::iterator it = L.begin();
std::advance(it, 2);
assert(it == L.end());
AsIucc
distance() et advance() prennent tout leur intrt avec la pro-
grammation gnrique (cest--dire avec les templates). Grce
elles, vous ntes plus oblig de connatre le type de conteneur
sur lequel vous travaillez. Ainsi, vous pouvez passer le type de
conteneur comme paramtre template, et le tour est jou :
votre algorithme devient gnrique.
145
Comprendre les itrateurs
sur fux dentre/lecture
#include <iterator>
class istream_iterator<T, Distance>;
Un istream_iterator<> est un InputIterator. Il effectue une
sortie formate dun objet de type T sur un istream<> parti-
culier donn. Quand la fn du fux est atteinte, listream_
iterator<> renvoie une valeur ditrateur particulire qui
signife fn de fux . La valeur de cet itrateur de fn
peut tre obtenue par le constructeur vide. Vous pourrez
noter que toutes les caractristiques dun InputIterator sont
applicables.
double somme = 0;
std::istream_iterator<double, char> is(std::cin);
while (is != std::istream_iterator<double, char>())
{
somme = somme + *is;
++is;
}
std::cout << Somme = << somme << std::endl;
Cet exemple lit des valeurs relles sur la console (jusqu
un Ctrl+Z) puis crit leur somme.
Lexemple suivant mmorise une suite dentiers, fournis
travers lentre standard, dans un tableau :
std::vector<int> V;
std::copy(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(V));
Lomprcndrc |cs IcraIcurs sur ux dcnIrccj|ccIurc
148 LhAPIJL 8 IIcraIcurs
Comprendre les itrateurs
sur fux de sortie/criture
#include <iterator>
class ostream_iterator<T>;
Un ostream_iterator<> est un OutputIterator qui effectue
une sortie formate dobjets de type T sur un ostream (fux
de sortie) particulier. Notez que toutes les restrictions
dutilisation dun OuputIterator doivent tre observes.
Lexemple suivant copie les lments dun vecteur sur la
sortie standard, en en crivant un par ligne :
std::vector<int> V;
//
std::copy(V.begin(), V.end(),

std::ostream_iterator<int>(std::cout, \n));
Utiliser les itrateurs
de parcours invers
#include <iterator>
class reverse_iterator<RandomAccessItertator, T,

Reference, Distance>;
class reverse_bidirectional_iterator<

BidirectionalIterator, T, Reference, Distance>;


reverse_iterator<> et reverse_bidirectional_iterator<>
sont des adaptateurs ditrateur qui permettent le parcours
invers dune squence. Appliquer loprateur ++ sur un
reverse_iterator<RandomAccessIterator> (ou un reverse
141
_bidirectional_iterator<BidirectionalIterator> revient
au mme quappliquer loprateur sur un RandomAccess
Iterator (ou un BidirectionalIterator). Les deux versions diff-
rent uniquement sur le concept ditrateur sur lequel elles
sappliquent.
template <class T>
void affcher_en_avant(const std::list<T>& L)
{
std::list<T>::iterator debut = L.begin();
std::list<T>::iterator fn = L.end();
while (debut != fn)
std::cout << *debut << std::endl;
}
template <class T>
void affcher_en_arriere(const std::list<T>& L)
{
typedef std::reverse_bidirectional_iterator<
std::list<T>::iterator,
T,
std::list<T>::reference_type,
std::list<T>::difference_type>
reverse_iterator;
reverse_iterator rdebut( L.begin() );
reverse_iterator rfn( L.end() );
while (rdebut != rfn)
std::cout << *rdebut << std::endl;
}
Dans la fonction affcher_en_avant(), les lments sont
affchs dans lordre : *debut, *(debut+1), , *(fn-1). Dans
la fonction affcher_en_arriere() les lments sont affchs
du dernier au premier : *(fn-1), *(fn-1), , *debut.
Si lon devait crire la deuxime fonction sur un std::
vector, il faudrait utiliser un std::reverse_iterator.
uI|scr |cs IcraIcurs dc parcours nvcrsc
148 LhAPIJL 8 IIcraIcurs
Utiliser les itrateurs dinsertion
#include <iterator>
class insert_iterator<Conteneur>;
insert_iterator<Conteneur> inserter(Conteneur& c,

Conteneur::iterator i);
insert_iterator<> est un adaptateur ditrateur qui fonc-
tionne comme un OutputIterator : une opration daffecta-
tion sur un insert_iterator<> insre un objet dans une
squence.
Lexemple suivant insre quelques lments dans une liste :
std::list<int> L;
L.push_front(3);
std::insert_iterator< std::list<int> > ii(L, L.begin());
*ii++ = 0;
*ii++ = 1;
*ii++ = 2;
std::copy(L.begin(), L.end(), std::ostream_iterator

<int>(std::cout, ));
// Affche : 0 1 2 3
Lexemple ci-aprs fusionne deux listes tries en insrant
le rsultat dans un set. Notez quun set (ou ensemble) ne
contient jamais deux lments identiques (doublons).
const int N = 6;
int A1[N] = { 1, 3, 5, 7, 9, 11 };
int A2[N] = { 1, 2, 3, 4, 5, 6 };
std::set<int> resultat;
std::merge(A1, A1+N, A2, A2+N,

std::inserer(resultat, resultat.begin()));
std::copy(L.begin(), L.end(), std::ostream_iterator

<int>(std::cout, ));
// Affche : 1 2 3 4 5 6 7 9 11
140
Utiliser les itrateurs dinsertion
en dbut de conteneur
#include <iterator>
class front_insert_iterator<FrontInsertionSequence>;
front_insert_iterator<FrontInsertionSequence>
front_inserer(FrontInsertionSequence & c);
front_insert_iterator<> est un adaptateur ditrateur qui
fonctionne comme un OutputIterator : une opration daffec-
tation sur un front_insert_iterator<> insre un objet juste
avant le premier lment dune squence. Le conteneur
doit supporter linsertion dun lment au dbut par la
fonction membre push_front(). Ce conteneur doit donc
supporter le concept de FrontInsertionSequence.
std::list<int> L;
L.push_front(3);
std::front_insert_iterator< std::list<int> > fi(L);
*fi++ = 0;
*fi++ = 1;
*fi++ = 2;
std::copy(L.begin(), L.end(), std::ostream_iterator

<int>(std::cout, ));
// Affche : 2 1 0 3
uI|scr |cs IcraIcurs dnscrIon cn dchuI dc conIcncur
150 LhAPIJL 8 IIcraIcurs
Utiliser les itrateurs dinsertion
en fn de conteneur
#include <iterator>
class back_insert_iterator<BackInsertionSequence>;
back_insert_iterator<BackInsertionSequence>

front_inserter(BackInsertionSequence & c);


back_insert_iterator<> est un adaptateur ditrateur qui
fonctionne comme un OutputIterator : une opration daf-
fectation sur un back_insert_iterator<> insre un objet
juste aprs le dernier lment dune squence. Le conte-
neur doit supporter linsertion dun lment la fn par la
fonction membre push_back(). Ce conteneur doit donc
supporter le concept de BackInsertionSequence.
std::list<int> L;
L.push_front(3);
std::back_insert_ierator< std::list<int> > bii(L);
*bii++ = 0;
*bii++ = 1;
*bii++ = 2;
std::copy(L.begin(), L.end(), std::ostream_iterator

<int>(std::cout, ));
// Affche : 3 0 1 2
9
LonIcncurs sIandard
La quasi-totalit des compilateurs modernes fournit une
implmentation de la STL (Standard Template Library,
bibliothque standard fournie avec tous les compilateurs
C++ modernes). Ce chapitre en rcapitule les principales
fonctions.
Les conteneurs standard fournis par la STL sont articuls
autour de quelques grandes familles, derrire lesquelles se
retrouvent les itrateurs vus au chapitre prcdent. Pour
chacune de ces familles, on retrouve, en bonne partie, les
mmes fonctions membres. Le tableau suivant donne la
liste des conteneurs STL regroups par famille.
Les chanes de caractres seront traites part, au chapitre
suivant.
Conteneurs STL par famille
ScqucnIc| AssocaIf AdapIaIcur
basic_string map priority_queue
string multimap queue
wstring set stack
deque multiset bitset
list
vector
152 LhAPIJL 0 LonIcncurs sIandard
Crer un conteneur
#include <header_du_conteneur>
Conteneur();
Conteneur(const allocator_type& allocateur);
Conteneur(const Conteneur&);
Conteneur(size_type n, const value_type& valeur);
Conteneur(size_type n, const value_type& valeur,

const allocator_type& allocateur);


Conteneur(InputIterator deb, InputIterator fn);
Conteneur(InputIterator deb, InputIterator fn,

const allocator_type& allocateur);


// pour les conteneurs associatifs
Conteneur(const _Compare& comparateur_de_cles);
Conteneur(const _Compare& comparateur_de_cles,

const allocator_type& allocateur);


Conteneur(InputIterator deb, InputIterator fn,

const _Compare& comparateur_de_cles);


Conteneur(InputIterator deb, InputIterator fn,

const _Compare& comparateur_de_cles, const

allocator_type& allocateur);
Crer un conteneur se fait toujours de la mme manire.
Vous pouvez crer un conteneur vide (constructeur par
dfaut) ou pr-initialis avec n valeur (valeur par dfaut
ou donne). Il est galement possible de crer un conte-
neur en copiant le contenu dun autre, totalement ou par-
tiellement travers les itrateurs.
Si un allocateur est fourni, il sera copi dans le conteneur.
Sinon, un allocateur par dfaut sera instanci et utilis.
Pour les conteneurs associatifs, des constructeurs suppl-
mentaires permettent de spcifer un foncteur utilis pour
comparer les cls (les conteneurs associatifs sont par essence
des conteneurs implicitement tris).
158
Par exemple, le code suivant cre un vecteur de cinq
entiers de valeur 42 :
std::vector<int> v(5,42);
Lhosr son conIcncur scqucnIc|
Dans un cadre gnral, utiliser std::vector<> est prfrable
std::deque<> et std::list<>. Un std::deque<> est utile si
vous insrez souvent en dbut ou fn de squence. Les std::
list<> et std::slist<> sont plus performants lorsque vous
insrez le plus souvent en milieu de squence. Dans la plupart
des autres situations, un std::vector<> sera le plus effcace.
Ajouter et supprimer dans
un conteneur squentiel
conteneur.insert(iter_pos, valeur);
conteneur.insert(iter_pos, n, valeur);
conteneur.insert(iter_pos, iter_debut, iter_fn);
conteneur.push_back(valeur);
conteneur.push_front(valeur);
conteneur.erase(iter_pos);
conteneur.erase(iter_debut, iter_fn);
conenteur.clear();
Linsertion se fait toujours juste avant la position indique
par litrateur. Lorsquune quantit n est fournie en plus
dune valeur, cette valeur est insre n fois par copie. Si
une squence [iter_debut, iter_fn[ est fournie, celle-ci
sera copie et insre. L encore, elle sera insre juste
avant la position iter_pos.
A|ouIcr cI supprmcr dans un conIcncur scqucnIc|
154 LhAPIJL 0 LonIcncurs sIandard
Info
Un appel conteneur.insert(p,n,t) est garanti dtre au
moins aussi rapide que dappeler n fois conteneur.insert(p,t).
Dans certains cas, il peut mme se rvler tre beaucoup plus
rapide.
push_back() et push_front() insrent, respectivement, la
valeur donne en fn ou en dbut de conteneur. Leur pen-
dant pour la suppression, pop_back() et pop_front() sont
disponibles suivant les conteneurs.
erase() supprime llment la position iter_pos donne,
ou toute la sous-squence [iter_debut, iter_fn[ donne. Il
va de soi que litrateur ou la squence doivent tre valides
et donc, par voie de consquence, pointer sur des lments
du conteneur utilis.
clear() efface toutes les valeurs du conteneur et le rend
vide. Notez toutefois que les structures internes du conte-
neur ne sont pas forcment libres et peuvent toujours
occuper de lespace mmoire. Ce choix provient dun
souci deffcacit lexcution (les oprations dallocation
et dsallocation mmoire sont lentes par nature). Si vous
tes dans un contexte ou lespace mmoire est plus impor-
tant, prenez bien garde ce phnomne.
Parcourir un conteneur
conteneur.begin();
conteneur.end();
conteneur.rbegin();
conteneur.rend();
La STL unife la manire de coder. Cet avantage se
retrouve dans la manire de parcourir tous les lments
155
dun conteneur. Ainsi, que vous ayez faire un tableau
(que lon peut aussi parcourir par indice), une liste ou un
arbre ( travers les std::map<> ou les std::set<>) il est
possible de procder toujours de la mme manire, grce
la notion ditrateur.
Vous trouverez dans le code ci-aprs tous les exemples de
parcours de conteneur : lendroit ou lenvers. Si vous
parcourez des conteneurs passs en arguments constants, il
vous sera ncessaire dutiliser des itrateurs dits constants.
std::Conteneur<>::iterator it;
for (it = conteneur.begin(); it != conteneur.end(); ++it)
{
//
}
std::Conteneur<>::const_iterator it;
for (it = conteneur.begin(); it != conteneur.end(); ++it)
{
//
}

std::Conteneur<>::reverse_iterator it;
for (it = conteneur.rbegin(); it != conteneur.rend();

++it)
{
//
}
std::Conteneur<>::const_reverse_iterator it;
for (it = conteneur.rbegin(); it != conteneur.rend();

++it)
{
//
}
Lorsque vous parcourez un conteneur associatif, vous ren-
contrez les lments selon lordre croissant (suivant la rela-
tion dordre fournie au type de conteneur) de leur cl.
Parcourr un conIcncur
158 LhAPIJL 0 LonIcncurs sIandard
Dans lexemple ci-aprs, nous remplissons un std::
set<int> avec quelques valeurs dans un ordre quelconque
et constatons que lors du parcours, nous les retrouvons
dans lordre croissant.
std::set<int> S;
S.insert(7);
S.insert(5);
S.insert(9);
S.insert(1);
S.insert(3);
for (std::set<int>::const_iterator it = S.begin();
it != S.end(); ++it)
{
std::cout << *it << ;
}
std::cout << std::endl;
// Affche: 1 3 5 7 9
Accder un lment
dun conteneur
conteneur.at(i);
conteneur[i];
conteneur.back();
conteneur.front();
conteneur.count(cle);
conteneur.fnd(cle);
Ces fonctions ne sont pas valables pour tous les conte-
neurs ; leur existence dpend du type de conteneur. Le
tableau suivant prcise la disponibilit de chacune delle
pour chaque conteneur.
151
Disponibilit des fonctions par conteneur
FoncIon LonIcncurs
at(i) std::basic_string<>, std::deque<>, std::vector<>
conteneur[] std::basic_string<>, std::deque<>, std::vector<>

std::map<>, std::multimap<>, std::set<>, std::multiset<>
1

back() std::deque<>, std::list<>, std::vector<>
front() std::deque<>, std::list<>, std::vector<>
count(cle) std::map<>, std::multimap<>, std::set<>, std::multiset<>
fnd(cle) std::map<>, std::multimap<>, std::set<>, std::multiset<>
1. Attention, en plus daccder llment, celui-ci sera cr sil nexiste
pas. Si vous ne voulez pas crer une entre, utilisez fnd(cle) plutt que
conteneur[cle] pour les conteneurs associatifs.
La fonction count() est un moyen simple de tester si une
cl est prsente dans un conteneur associatif. Toutefois, si
vous souhaitez tester la prsence de la cl puis ventuelle-
ment utiliser la valeur associe, utilisez plutt un fnd(),
comme lillustre le code suivant :
std::map<int,int> M;
//
std::map<int,int>::iterator it = M.fnd(3);
if (it != M.end())
{
std::cout << 3 existe et est associ << it->second
<< std::endl
<< La valeur de la cl est bien << it->frst
<< std::endl;
}
else
std::cout << La cl 3 nest pas prsente dans M.\n;
Acccdcr a un c|cmcnI dun conIcncur
158 LhAPIJL 0 LonIcncurs sIandard
Crer et utiliser un tableau
#include <vector>
std::vector<Type> V;
Les vecteurs de la STL sont des vecteurs dynamiques (leur
taille peut changer au cours de la vie du programme). Ils
font parti des conteneurs dits squentiels. De fait, linser-
tion et la suppression dlments la fn dun vecteur sef-
fectuent en temps quasi constant. En dbut ou en tout
autre endroit qu la fn, le temps de ces oprations sera
proportionnel au nombre dlments prsents aprs le lieu
dinsertion. Le type ditrateur associ aux vecteurs est de
type RandomAccesIterator, autrement dit accs direct.
AIIcnIon
La bibliothque STL spcialise le type std::vector<bool>.
Celui-ci permet de stocker linformation au niveau du bit par
lintermdiaire de masques. Si cela lavantage dutiliser trs
peu de mmoire, il en cote un trs fort impact sur les perfor-
mances. Si les performances sont primordiales pour vous, pr-
frez-lui un std::vector<unsigned char>.
Le dernier constructeur cre un vecteur contenant une
copie des lments entre debut et fn. Considrez lexemple
suivant :
// Cre un vecteur dentiers alatoires
std::vector<int> v(10) ;
std::cout << vecteur original : ;
for (int i=0; i<v.size(); i++)
std::cout << (v[i] = (int) rand() % 10) << ;
std::cout << std::endl;
150
// trouver le premier lment pair du tableau
std::vector<int>::iterator it1 = v.begin();
while (it1!=v.end() && *it1%2 !=0)
it1++;
// trouver le dernier lment pair du tableau
std::vector<int>::iterator it2 = v.end();
do { it2--; } while (it1!=v.begin() && *it1%2 !=0) ;
// si au moins un lment trouv
if (it1 != v.end())
{
std::cout << premier nombre pair : << *it1
<< , dernier nombre pair : << *it2
<< std::endl
<< nouveau vecteur : ;
std::vector<int> v2(it1, it2);
for (int i=0; i<v2.size(); i++)
std::cout << v2[i] << ;
std::cout << std::endl;
}
Son excution produira la sortie suivante :
vecteur original : 1 7 8 3 4 2 0 8 6 5
premier nombre pair : 8, dernier nombre pair : 6
nouveau vecteur : 8 3 4 2 0 8 6
AIIcnIon
Les itrateurs sur les vecteurs ne sont gnralement pas stables
linsertion ou la suppression dlments. En effet, les l-
ments tant stocks de manire contigu, ceux-ci peuvent
physiquement changer de place en mmoire et les itrateurs
devenir invalides. Mme linsertion en fn de vecteur : cette
opration peut ncessiter une augmentation de la taille rser-
ve impliquant le dplacement de tous les lments.
Lrccr cI uI|scr un Iah|cau
180 LhAPIJL 0 LonIcncurs sIandard
Info
Pour de petites squences, les vecteurs sont plus performants
que les listes. Si donc vous utilisez de petites squences et que
la stabilit des itrateurs nest pas importante pour vous, pr-
frez-les aux listes.
Crer et utiliser une liste chane
#include <list>
std::list<Type> L;
Les listes STL sont des listes doublement chanes. La plu-
part des implmentations utilisent un chanon sans donne
comme tte/queue de liste. Un chanon correspond un
itrateur. Le chanon de tte se retrouve travers un appel
de la fonction membre end(). Les itrateurs des listes sont
garantis comme stables linsertion et la suppression (pour
autant que ce ne soit pas celui que vous supprimiez).
AIIcnIon
Dans certaines implmentations de la STL, un itrateur de
liste est plus quun pointeur sur un maillon, et contient aussi
dautres informations. Cest par exemple le cas avec limpl-
mentation de Microsoft Visual C++ 8, o il peut atteindre la
taille de trois pointeurs en mode debug (celui sur le maillon
plus un sur la liste et un autre sur le conteneur, mais qu-
importe puisque leur implmentation a encore chang avec
VC++ 9).
181
Le parcours dune liste chane seffectue grce aux itra-
teurs :
std::list<int> L;
//
for (std::list<int>::iterator it = L.begin(); it !=

L.end(); ++it)
{
// accs llment
// avec (*it).methode() ou it->methode()
}
Vous pouvez facilement parcourir une liste lenvers
laide des itrateurs inverss :
std::list<int> L;
//
for (std::list<int>::reverse_iterator it = L.rbegin();
it != L.rend(); ++it)
{
// accs llment
// avec (*it).methode() ou it->methode()
}
Si vous tes dans une fonction o la liste que vous utilisez
est fournie en rfrence constante, il vous faudra utiliser
des itrateurs constants (par exemple, std::list<int>::
const_iterator).
Crer et utiliser une fle
double entre
#include <deque>
std::deque<Type> D;
Les fles doubles entres sont un peu comme des piles dans
lesquelles il est possible dajouter et de retirer un lment
Lrccr cI uI|scr unc |c a douh|c cnIrcc
182 LhAPIJL 0 LonIcncurs sIandard
au dbut (avec push_front() et pop_front()) ou la fn (avec
push_back() et pop_back()). Laccs au dbut et la fn se
fait avec front() et back(). De plus, laccs par indice
demeure possible et reste en temps constant travers lop-
rateur [] et la fonction at() qui fournit en plus un contrle
des bornes.
La stabilit des itrateurs que vous auriez stocks nest pas
garantie, sauf en cas de suppression en tte ou en queue de
fle.
AsIucc
Les fles double entre permettent de coder facilement des
conteneurs First In First Out (FIFO), ou premier entr, premier
sorti . Pour ce faire, il sufft dutiliser push_front() et pop_
pack() conjointement. Le code suivant pourrait tre un moyen
trs simple de la simuler laide dune std::deque<> :
template <class T>
struct FIFO
{
inline T pop() { return m_values.pop_back(); }
inline void push(const T& v) { m_values.push_front(v); }
protected:
std::deque<T> m_values;
};
Mais ne vous donnez pas cette peine ! Pour les conteneurs FIFO,
la STL fournie les std::queue<>. Et pour les conteneurs LIFO, vous
disposez des std::stack<> (piles).
188
Crer et utiliser une pile
#include <stack>
std::stack<Type,Conteneur> S;
std::stack<Type> S;
Une pile supporte linsertion et la suppression dlments
une seule extrmit travers push() et pop(). Du coup,
on retrouve la rgle du dernier insr, premier sorti ,
typique dun conteneur LIFO (Last In First Out). Laccs
au dernier lment empil se fait avec top().
Vous pouvez dfnir une pile avec nimporte quel conte-
neur squentiel comme std::deque<>, std::list<> ou
std::vector<>. Si vous ne spcifez pas le type de conte-
neur utiliser, un std::deque<> le sera par dfaut.
AIIcnIon
Le constructeur dune pile prenant pour argument un conte-
neur (dont le type doit correspondre au type de conteneur spcif
dans linstanciation) neffectue pas un lien vers ce conteneur
pour lutiliser mais copie bel et bien tous ses lments au sein
de la pile ainsi cre.
std::deque<int> D;
D.push_back(1);
D.push_back(2);
D.push_back(3);
std::stack<int> S(D);
// S contient 1 2 3
D[1] = 20;
// D contient 1 20 3
// S contient toujours 1 2 3

Lrccr cI uI|scr unc p|c
184 LhAPIJL 0 LonIcncurs sIandard
Crer et utiliser une queue
#include <queue>
std::queue<Type,Conteneur> Q;
std::queue<Type> Q;
Une queue supporte linsertion dlments en dbut de
conteneur (avec push()) et la suppression dlments en fn
de conteneur (avec pop()). On retrouve la rgle du pre-
mier insr, premier sorti typique dun conteneur FIFO
(First In First Out). Laccs au dernier lment empil se
fait avec front() et laccs au prochain lment dpil avec
back().
Vous pouvez dfnir une queue avec nimporte quel
conteneur squentiel comme std::deque<>, std::list<>
ou std::vector<>. Si vous ne spcifez pas le type de conte-
neur utiliser, un std::deque<> le sera par dfaut.
Pour dterminer si une queue est vide, utilisez empty(). Pour
connatre le nombre dlments quelle contient, utilisez
size().
Info
Les piles, queues et queues de priorits sont des adaptateurs,
bass sur des conteneurs de la STL. Si vous voulez crer vos
propres conteneurs en les basant sur des conteneurs (ou adap-
tateurs) de la STL, nhsitez pas regarder comment ces classes
sont crites. Vous pourrez glaner ainsi beaucoup de techniques
et ides utiles pour maximiser leur compatibilit avec la STL et
prenniser votre code.
185
Crer et utiliser une queue
de priorit
#include <priority_queue>
std::priority_queue<Type,Conteneur,RelationDOrdre> PQ;
std::priority_queue<Type,Conteneur> PQ;
std::priority_queue<Type> PQ;
Une queue de priorit est une queue un peu particulire :
elle classe ses lments de telle sorte que le prochain l-
ment dpiler corresponde llment le plus prioritaire.
Un lment est dfni comme plus prioritaire sil se trouve
en dbut de liste aprs ordonnancement suivant la relation
dordre fournie (la relation dordre par dfaut est std::
less<Type>).
Le conteneur utilis par dfaut est un std::vector<>. Vous
pouvez utiliser nimporte quel conteneur supportant lac-
cs direct (cest--dire par indice). En effet, pour classer ses
lments, un tel conteneur utilise les algorithmes std::
make_heap(), std::push_heap() et std::pop_heap() qui repo-
sent sur ce concept.
Linsertion se fait avec push(), et la suppression ou dpile-
ment avec pop(). Linterrogation de llment le plus prio-
ritaire se fait avec top(). Comme dhabitude, size()
retourne le nombre dlments prsents et empty()indique
si le conteneur est vide.
AIIcnIon
pop() ne renvoie pas llment mais se contente de supprimer
llment le plus prioritaire du conteneur.
Lrccr cI uI|scr unc qucuc dc prorIc
188 LhAPIJL 0 LonIcncurs sIandard
Crer et utiliser un ensemble
#include <set>
std::set<Type, RelationDOrdre> S;
std::set<Type> S;
std::multiset<Type, RelationDOrdre> MS;
std::multiset<Type> MS;
Les ensembles, simples ou multiples, sont des conteneurs
associatifs simples : ils nont pas de valeur associe chaque
cl, la cl elle-mme faisant offce de valeur. Ce sont des
conteneurs tris. Un ensemble simple std::set<> ne peut
pas contenir deux lments identiques, alors quun ensem-
ble multiple std::multiset<> lautorise.
Les itrateurs sur les ensembles sont stables linsertion
et la suppression dlments, lexception (bien sr) de
ceux pointant sur des lments retirs de lensemble
considr.
Pour insrer des lments, utilisez insert(elt). Cette fonc-
tion renvoie une std::pair<iterator,bool> contenant
lemplacement de la valeur insre si second vaut vrai, ou
de lemplacement de la valeur dj existante si second vaut
faux. Si vous connaissez dj lendroit o insrer la valeur,
utilisez plutt insert(iter_pos,valeur) qui garantit dans
ce cas une insertion en temps constant.
181
Crer et utiliser une table
associative
#include <map>
std::map<Cle, Type, RelationDOrdre> M;
std::map<Cle, Type> M;
std::multimap<Cle, Type, RelationDOrdre> M;
std::multimap<Cle, Type> M;
Les tables associatives permettent dassocier une cl une
(pour les std::map<>) ou plusieurs valeurs (pour les std::
multimap<>) dun Type donn. La relation dordre utilise
par dfaut est le foncteur std::less<Cle>, qui utilise lop-
rateur < par dfaut. Pour chercher un lment sans crer
dentre dans le conteneur, nutilisez pas loprateur []
mais plutt la fonction membre fnd() qui renvoie un it-
rateur sur llment trouv ou litrateur end() sinon.
Lexemple suivant montre comment obtenir toutes les
valeurs associes une cl dans un std::multimap<>.
typedef std::multimap<TypeCle,TVal>::const_iterator

ConstIter;
std::pair<ConstIter,ConstIter> bound = mm.equal_range

(ma_cle);
for (ConstIter it = bound.frst; it != bound.second; ++it)
//
Lrccr cI uI|scr unc Iah|c assocaIvc
188 LhAPIJL 0 LonIcncurs sIandard
Lexemple dutilisation suivant illustre comment retrouver
le nombre de jours dans un mois en fonction du nom du
mois :
std::map<std::string, int> mois;
std::map<std::string, int>::iterator it_cour, it_avant,

it_apres;
mois[std::string(janvier)] = 31;
mois[std::string(fvrier)] = 28;
mois[std::string(mars)] = 31;
//
mois[std::string(dcembre)] = 31;

std::cout << mars : << mois[std::string(mars)]

<< std::endl;
it_cour = mois.fnd(june);
it_avant = it_apres = it_cour;
++it_apres;
--it_avant;
std::cout << Avant (en ordre alphabtique) :
<< it_avant->frst << std::endl;
std::cout << Aprs (en ordre alphabtique) :
<< it_apres->frst << std::endl;
Linsertion dans les std::multimap<> est un peu moins
intuitive. Lexemple suivant montre comment utiliser ce
conteneur :
struct ltstr
{
bool operator()(const char* s1, const char* s2)
const
{
return strcmp(s1, s2) < 0;
}
};
//
std::multimap<const char*, int, ltstr> m;
std::multimap<const char*, int, ltstr>::iterator it;
180

m.insert(std::pair<const char* const, int>(a, 1));
m.insert(std::pair<const char* const, int>(c, 2));
m.insert(std::pair<const char* const, int>(b, 3));
m.insert(std::pair<const char* const, int>(b, 4));
m.insert(std::pair<const char* const, int>(a, 5));
m.insert(std::pair<const char* const, int>(b, 6));

std::cout << Nombre dlments avec a pour cle :

<< m.count(a) << std::endl;


std::cout << Nombre dlments avec b pour cle :

<< m.count(c) << std::endl;


std::cout << Nombre dlments avec c pour cle :

<< m.count(c) << std::endl;



std::cout << Nombre dlments dans m : << std::
endl;
for (it = m.begin(); it != m.end(); ++it)
{

std::cout << < << it->frst << , << it->second

<< > << std::endl;


}
Info
Les std::map<> et std::multimap<> sont gnralement
bases sur des arbres binaires quilibrs. Linsertion et la
recherche dlments seffectue donc en temps O(log n). Si
cela est suffsant dans bien des cas, ce peut tre pnalisant
dans dautres. Si donc vous avez besoin de meilleures perfor-
mances, vous pouvez vous tourner, au prix dune occupation
mmoire plus importante, vers dautres solutions. Avant de
dvelopper les vtres, essayez les tables de hachage fournies
par la STL. Leur temps daccs et dinsertion est en temps quasi
constant, comme cela est expliqu la section suivante.
Lrccr cI uI|scr unc Iah|c assocaIvc
110 LhAPIJL 0 LonIcncurs sIandard
Crer et utiliser une table
de hachage
#include <hash_set>
std::hash_set<Cle[,FonctionDeHash[,TestEgaliteCle]]>

M;
std::hash_multiset<Cle[,FonctionDeHash[,

TestEgaliteCle]]> M;
#include <hash_map>
std::hash_map<Cle,Type[,FonctionDeHash[,

TestEgaliteCle]]> M;
std::hash_multimap<Cle,Type[,FonctionDeHash[,

TestEgaliteCle]]> M;
AIIcnIon
Avec g++, vous trouverez ces classes dans <ext/hash_set> et
<ext/hash_map>.
Les tables de hachage sont plus performantes que les
conteneurs associatifs (map et set) mais nordonnent pas les
lments en fonction de leur cl. Elle repose sur le calcul
dune sous-cl de type entier pour donner un indice dans
un tableau contenant (suivant le type de table de hachage
utilis) des maps ou des sets multiples ou non.
111
Le foncteur de test dgalit des cls par dfaut est std::
equal_to<Cle>. La fonction de hachage par dfaut est le
foncteur std::hash<Cle>.
Lutilisation des tables de hachage est comparable celle
des tables associatives et des ensembles suivant le cas.
Les fonctions de hachage par dfaut supportent les types
suivants : char*, const char*, char, signed char, unsigned
char, short, unsigned short, int, unsigned int, long et unsi-
gned long, plus std::crope<> et std::wrope<> pour une ges-
tion effcace au niveau des chanes de caractres. Si vous
voulez crire vos propres fonctions de hachage pour vos
types personnaliss, sachez que ce foncteur doit imprati-
vement retourner un std::size_t, comme le montre le
modle suivant :
struct MonHash
{
std::size_t operateor()(const MaCle& cle)
{
// calcul
}
};
Lrccr cI uI|scr unc Iah|c dc hachagc
112 LhAPIJL 0 LonIcncurs sIandard
Connatre la complexit des fonctions
membres des conteneurs
Comparaison des complexits
0roupc FoncIon vccIor dcquc |sI scI mu|IscI map mu|Imap hIscI sIack qucuc prorIy_qucuc
Constructeur * * * * * * * * * * *
Destructeur O(n) O(n) O(n) O(n) O(n) O(n) O(n) - - - -
operateur= O(n) O(n) O(n) O(n) O(n) O(n) O(n) O(1)
4
- - -
Itrateurs begin O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
end O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
rbegin O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
rend O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
Capacit size O(1) O(1) O(1)
1
O(1) O(1) O(1) O(1) O(1) O(1) O(1) O(1)
max_size O(1) O(1) O(1)
1
O(1) O(1) O(1) O(1) - - - -
empty O(1) O(1) O(1) O(1) O(1) O(1) O(1) - O(1) O(1) O(1)
resize O(n) O(n) O(n) - - - - - - - -
Accs front O(1) O(1) O(1) - - - - - - O(1) -
back O(1) O(1) O(1) - - - - - - O(1) -
top - - - - - - - - O(1) - O(1)
operator[] O(1) O(1) - - - Log - O(1)
4
- - -
at O(1) O(1) - - - - - - - - -
Modifeurs assign O(n) O(n) O(n) - - - - - - - -
insert O(n+m) O(m)
2
O(m) Log
3
Log
3
Log
3
Log
3
- - - -
118
Connatre la complexit des fonctions
membres des conteneurs
Comparaison des complexits
0roupc FoncIon vccIor dcquc |sI scI mu|IscI map mu|Imap hIscI sIack qucuc prorIy_qucuc
Constructeur * * * * * * * * * * *
Destructeur O(n) O(n) O(n) O(n) O(n) O(n) O(n) - - - -
operateur= O(n) O(n) O(n) O(n) O(n) O(n) O(n) O(1)
4
- - -
Itrateurs begin O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
end O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
rbegin O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
rend O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
Capacit size O(1) O(1) O(1)
1
O(1) O(1) O(1) O(1) O(1) O(1) O(1) O(1)
max_size O(1) O(1) O(1)
1
O(1) O(1) O(1) O(1) - - - -
empty O(1) O(1) O(1) O(1) O(1) O(1) O(1) - O(1) O(1) O(1)
resize O(n) O(n) O(n) - - - - - - - -
Accs front O(1) O(1) O(1) - - - - - - O(1) -
back O(1) O(1) O(1) - - - - - - O(1) -
top - - - - - - - - O(1) - O(1)
operator[] O(1) O(1) - - - Log - O(1)
4
- - -
at O(1) O(1) - - - - - - - - -
Modifeurs assign O(n) O(n) O(n) - - - - - - - -
insert O(n+m) O(m)
2
O(m) Log
3
Log
3
Log
3
Log
3
- - - -
LonnaIrc |a comp|cxIc dcs foncIons mcmhrcs dcs conIcncurs
114 LhAPIJL 0 LonIcncurs sIandard
Comparaison des complexits (Suite)
0roupc FoncIon vccIor dcquc |sI scI mu|IscI map mu|Imap hIscI sIack qucuc prorIy_qucuc
erase O(n)
5
O(m)
6
O(m) O(1)+
7
O(1)+
7
O(1)+
7
O(1)+
7
- - - -
swap O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
clear O(n) O(n) O(n) O(n) O(n) O(n) O(n) - - - -
push_front - O(1) O(1) - - - - - - - -
pop_front - O(1) O(1) - - - - - - - -
push_back O(1) O(1) O(1) - - - - - - - -
pop_back O(1) O(1) O(1) - - - - - - - -
push - - - - - - - - O(1) O(1) O(1)
pop - - - - - - - - O(1) O(1) O(1)
Observeurs key_comp - - - O(1) O(1) O(1) O(1) - - - -
value_comp - - - O(1) O(1) O(1) O(1) - - - -
Oprations fnd - - - Log Log Log Log - - - -
count - - - Log Log Log Log - - - -
lower_bound - - - Log Log Log Log - - - -
upper_bound - - - Log Log Log Log - - - -
equal_range - - - Log Log Log Log - - - -
1. En O(n) dans certaines implmentations.
2. En O(n+m) dans certaines implmentations (m est le nombre dlments insrer).
3. insert(x) est logarithmique (O(log n)) ; insert(position) est en gnral logarith-
mique (O(log n)), mais peut tre en temps constant amorti (O(1)+) si x est insr
juste aprs llment point par position ; insert(frst, last) est gnralement
en m xlog(n+m), o m est le nombre dlments insrer et n la taille du conte-
neur avant insertion, mais linaire (O(m)) si les lments insrs sont tris avec le
mme critre que le conteneur.
115
Comparaison des complexits (Suite)
0roupc FoncIon vccIor dcquc |sI scI mu|IscI map mu|Imap hIscI sIack qucuc prorIy_qucuc
erase O(n)
5
O(m)
6
O(m) O(1)+
7
O(1)+
7
O(1)+
7
O(1)+
7
- - - -
swap O(1) O(1) O(1) O(1) O(1) O(1) O(1) - - - -
clear O(n) O(n) O(n) O(n) O(n) O(n) O(n) - - - -
push_front - O(1) O(1) - - - - - - - -
pop_front - O(1) O(1) - - - - - - - -
push_back O(1) O(1) O(1) - - - - - - - -
pop_back O(1) O(1) O(1) - - - - - - - -
push - - - - - - - - O(1) O(1) O(1)
pop - - - - - - - - O(1) O(1) O(1)
Observeurs key_comp - - - O(1) O(1) O(1) O(1) - - - -
value_comp - - - O(1) O(1) O(1) O(1) - - - -
Oprations fnd - - - Log Log Log Log - - - -
count - - - Log Log Log Log - - - -
lower_bound - - - Log Log Log Log - - - -
upper_bound - - - Log Log Log Log - - - -
equal_range - - - Log Log Log Log - - - -
LonnaIrc |a comp|cxIc dcs foncIons mcmhrcs dcs conIcncurs
4. Avec un surcot non ngligeable d au calcul de dcalage et de masque.
5. Linaire en fonction du nombre dlments effacer (O(m)), plus le nombre
dlments dplacer aprs le dernier lment effac (O(m+n pos)).
6. Linaire en fonction du nombre dlments effacs (O(m)). Dans certaines
implmentations, ajoute galement un temps linaire au nombre dlments res-
tant aprs les lments supprims (O(m+npos)).
7. erase(position) est en temps constant amorti (O(1)+) ; erase(x) est en O(log n) ;
erase(frst,last) est en O(log n) + O(m).
118 LhAPIJL 0 LonIcncurs sIandard
Fonctions spcifques
LonIcncur FoncIons
vector capacity, reserve, splice
list splice, reserve, remove, remove_if, unique, merge, sort
bitset set, reset, fip, to_ulong, to_string, test, any, none
10
Lhancs dc
caracIcrcs
Les chanes de caractres sont utilises dans pratiquement
tous les programmes informatiques, du moins la quasi-
totalit de ceux communiquant avec lhomme. Manipuler
de simples pointeurs sur des char (ou wchar_t) est non
seulement risqu (dbordement de mmoire) mais devient
totalement caduc lorsque lon dsire rendre son pro-
gramme polyglotte. Pour ce faire, la STL fournit diffrent
types de chanes de caractres sintgrant parfaitement avec
les algorithmes de la STL (le contraire aurait t surpre-
nant) mais surtout facilitant la vie du programmeur.
Dautres implmentations existent comme les QString de
QT ou les wxString de wxWidgets. Ils ont parfois des
avantages par rapport ceux de la STL (ne serait-ce que
leur intgration au sein de leur bibliothque respective)
mais aussi leurs inconvnients. Il faut donc opter pour
lun ou lautre en fonction de vos besoins. Il nest pas rare
de les voir cohabiter dans des programmes dune certaine
envergure.
118 LhAPIJL 10 Lhancs dc caracIcrcs
Crer une chane
#include <string>
std::string une_chaine;
#include <wstring>
std::wstring une_chaine_unicode;
Les chanes de caractres de la STL ne sont pas forcment
des chanes AZT ( zro terminal). Elles dpassent cette
limite en embarquant simplement le nombre de caractres.
On obtient ainsi directement la taille de ces chanes avec
la fonction membre size(). Notez quil sagit bien ici du
nombre de caractres et non du nombre doctets. Les std::
string<> stockent des chanes dont le jeu de caractres
stend sur 8 bits maximum, et les std::wstring<> sont
ddies aux chanes utilisant un jeu de caractres tendus
comme Unicode.
Info
Si vous manipulez de trs grosses chanes de caractres, exa-
minez les std::crope<> et std::wrope<>.
#include <rope> // <ext/rope> sous G++
std::crope c;
std::wrope w;
Elles sont stockes sous une forme volutive conue pour
rendre effcace les traitements impliquant la chane dans son
ensemble. Ainsi, des oprations comme laffectation, la concat-
nation et lextraction de sous-chanes prendront un temps pres-
que indpendant de la taille de la chane. Par contre, remplacer
un caractre dans une rope est coteux, de mme que la parcou-
rir caractre par caractre. Cest un peu le revers de la mdaille
(sinon quelle serait lutilit des string ?).
110
Les constructeurs de chanes de caractres supportent plu-
sieurs formes dinitialisation. Lexemple suivant en dresse
la liste et leurs ventuelles limitations :
std::string s1; // une chane vide
std::string s2(abc\x00def); // contiendra abc
std::string s3 = abc\x00def; // contiendra abc
std::string s4(abc\x00def,6); // contiendra abc\x00de
std::string s5(5,a); // contiendra aaaaa
std::string s6(s5); // contiendra une copie de s5
std::string s7(s4,2,3); // contiendra c\x00d
std::set<char> aSet;
aSet.insert(e); aSet.insert(a);aSet.insert(z);
std::string s8(aSet.begin(),aSet.end()); // contiendra aez
s1 = s3; // contiendra une copie de s3
Si vous avez besoin dobtenir une conversion en chane AZT
dune std::string, utilisez la fonction membre c_str() qui
ajoutera un caractre nul si il ny tait pas (sans modifer
la taille de votre chane), avant de retourner un pointeur
sur le premier caractre. Attention toutefois, si votre
chane contient dj en son sein un caractre nul, vous
retrouverez les mmes restrictions quavec les chanes C
classiques
AsIucc
Si vous avez besoin de rinitialiser une chane, utilisez les
fonctions membres assign(). Elles prennent les mmes argu-
ments que les diffrents constructeurs mais offrent lavantage
dviter de crer un objet temporaire dans certains cas.
Lrccr unc chanc
180 LhAPIJL 10 Lhancs dc caracIcrcs
Connatre la longueur
dune chane
#include <string>
bool string::empty();
bool string::length();
bool string::size();
La fonction empty() indique si la chane est vide. Les fonc-
tions length() et size() sont identiques et renvoient la
longueur de la chane.
Comparer des chanes
int string::compare(const string& s2);
int string::compare(const char* s2);
int string::compare(size_type index, size_type len,

const string& s2);


int string::compare(size_type index, size_type len,

const string& s2, size_type index_s2, size_type

len_s2);
int string::compare(size_type index, size_type len,

const char* s2, size_type len_s2);


La fonction membre compare() permet de comparer la
chane considre (s1) avec une autre (s2). Si le rsultat est
ngatif, alors s1 < s2. Si le rsultat est nul, alors s1 == s2.
Enfn si le rsultat est positif, alors s1 > s2. Notez que ces
oprateurs de comparaison (<, > et ==) existent galement,
mais prenez garde lallocation dynamique si vous com-
parez une chane un char*.
181
std::string noms[] = {
Alfred, Robin, 5e lment, inconnu
};
for (int i=0; i<4; ++i)
{
for (int j=0; j<4; ++j)
std::cout << noms[i].compare( noms[j] ) << ;
std::cout << std::endl;
}
changer le contenu
de deux chanes
void string::swap(string& s2);
void swap(string& s1, string& s2);
Les fonctions swap() sont beaucoup plus performantes que
dutiliser une variable temporaire de type std::string.
Elles effectuent un change de la taille et du pointeur
interne plutt que de recopier toutes les chanes, ce qui est
videmment beaucoup plus rapide.
std::string s1 = Premire chane;
std::string s2 = Deuxime contenu;
s1.swap(s2);
std::cout << s1 << std::endl; // Deuxime contenu
std::cout << s2 << std::endl; // Premire chane
Lchangcr |c conIcnu dc dcux chancs
182 LhAPIJL 10 Lhancs dc caracIcrcs
Rechercher une sous-chane
size_type string::fnd(const string& str, size_type

index);
size_type string::fnd(const char* str, size_type

index);
size_type string::fnd(const char* str, size_type

index, size_type length);


size_type string::fnd(char ch, size_type index);
size_type string::rfnd(const string& str, size_type

index);
size_type string::rfnd(const char* str, size_type

index);
size_type string::rfnd(const char* str, size_type

index, size_type num);


size_type string::rfnd(char ch, size_type index);
size_type string::fnd_frst_not_of(const string&

str, size_type index = 0);


size_type string::fnd_frst_not_of(const char* str,

size_type index = 0 );
size_type string::fnd_frst_not_of(const char* str,

size_type index, size_type num);


size_type string::fnd_frst_not_of(char ch,

size_type index = 0);


size_type string::fnd_frst_of(const string &str,

size_type index = 0);


size_type string::fnd_frst_of(const char* str,

size_type index = 0);


size_type string::fnd_frst_of(const char* str,

size_type index, size_type num);


size_type string::fnd_frst_of(char ch, size_type

index = 0);
188
size_type string::fnd_last_not_of(const string& str,

size_type index = npos);


size_type string::fnd_last_not_of(const char* str,

size_type index = npos );


size_type string::fnd_last_not_of(const char* str,

size_type index, size_type num);


size_type string::fnd_last_not_of(char ch, size_type

index = npos);
size_type string::fnd_last_of(const string &str,

size_type index = npos);


size_type string::fnd_last_of(const char* str,

size_type index = npos);


size_type string::fnd_last_of(const char* str,

size_type index, size_type num);


size_type string::fnd_last_of(char ch, size_type

index = npos);
Dans tous les cas, ces fonctions renvoient soit lindice de la
position dans la chane considre (celle qui correspond
au this de la fonction membre), soit string::npos si rien
nest trouv.
Les fonctions fnd() renvoient lindice o se trouve la pre-
mire occurrence de la chane str ou du caractre ch
recherch. Lorsque le paramtre length est donn, la fonc-
tion ne recherchera que les length premiers caractres de
str. Le paramtre index permet de prciser le point de
dpart de la recherche (ceci permet de trouver les occur-
rences suivantes).
Les fonctions rfnd() effectuent la recherche en remontant
vers le dbut de la chane en partant de lindex donn.
std::string str1( Alpha Beta Gamma Delta );
std::string::size_type loc = str1.fnd( Omega, 0 );
if( loc != std::string::npos )
std::cout << Found Omega at << loc << std::endl;
else
std::cout << Didnt fnd Omega << std::endl;
cchcrchcr unc sous-chanc
184 LhAPIJL 10 Lhancs dc caracIcrcs
Les fonctions fnd_frst_not_of() recherchent le premier
caractre nappartenant pas str (ou diffrent de ch). L
encore, il est possible de ne considrer que les num premiers
caractres de str, et ne commencer la recherche qu lin-
dex voulu.
Les fonctions fnd_frst_of() recherchent le premier carac-
tre appartenant str. Les fonctions fnd_last_not_of() et
fnd_last_of() sont comme ce que rfnd() est fnd(), mais
recherchent nimporte quel caractre de la chane plutt
que la chane elle-mme.
Lexemple ci-aprs recherche le premier caractre qui ne
soit pas une minuscule. Il affchera la valeur 33.
std::string minuscule = abcdefghijklmnopqrstuvwxyz ,-;
std::string chaine = ceci est la partie en minuscule,

ET CELLE-CI EST LA PARTIE EN MASJUCULE;


std::cout << la premire lettre non minuscule dans la

chane est lindice : << chaine.fnd_frst_not_of

(minuscule) << std::endl;


Extraire une sous-chane
string string::substr(size_type index, size_type

length = npos);
La fonction substr() retourne la sous-chane commen-
ant lindice index et de taille length. Si ce dernier para-
mtre nest pas fourni, la sous-chane contiendra tous les
caractres suivant lindex donn, jusqu la fn.
AIIcnIon
La sous-chane renvoye est une copie des caractres et nest
pas un lien vers une sous-partie de la chane dorigine.
185
Rien ne vaut un exemple pour comprendre immdiate-
ment. En voici donc un trs simple :
std::string s(What we have here is a failure to

communicate);
std::string sub = s.substr(21);
std::cout << La chane originale est : << s << std::endl;
std::cout << La sous-chane est : << sub << std::endl;
Il produira le rsultat suivant :
La chane originale est : What we have here is a

failure to communicate
La sous-chane est : a failure to communicate
Remplacer une partie
dune chane
string& string::replace(size_type index, size_type

num, const string& str);


string& string::replace(size_type index1, size_type

num1, const string& str, size_type index2,

size_type num2);
string& string::replace(size_type index, size_type

num, const char* str);


string& string::replace(size_type index, size_type

num1, const char* str, size_type num2);


string& string::replace(size_type index, size_type

num1, size_type num2, char ch);


string& string::replace(iterator start, iterator

end, const string& str);


string& string::replace(iterator start, iterator

end, const char* str);


string& string::replace(iterator start, iterator

end, const char* str, size_type num);


string& string::replace(iterator start, iterator

end, size_type num, char ch);


cmp|accr unc parIc dunc chanc
188 LhAPIJL 10 Lhancs dc caracIcrcs
Les fonctions replace() font, au choix, les actions suivantes :
remplacer les caractres de la chane courante avec au plus
num caractres de str, en commenant lindex donn ;
remplacer jusqu' num1 caractres de la chane courante
(en commenant lindex1) avec au plus num2 caractres
de str en partant de lindex2 ;
remplacer jusqu' num caractres de la chane courante
par ceux de str, en commenant lindice index ;
remplacer jusqu' num1 caractres de la chane courante
(en partant de lindice index1) par les num2 caractres de
str partir de lindice index2 ;
remplacer jusqu' num1 caractres de la chane courante
(en commenant lindice index) avec num2 copies du
caractre ch ;
remplacer les caractres de la chane courante depuis
start jusqu end avec la chane str ;
remplacer les caractres de la chane courante depuis start
jusqu end avec les num premiers caractres de str ;
remplacer les caractres de la chane courante depuis
start jusqu end avec num copies du caractre ch.
Par exemple, le code suivant affche la chane Ils disent
que a ressemble un truc trs cool, Vincent.
std::string s = Ils disent que a ressemble ... un

trs GROS truc!;


std::string s2 = un truc trs cool, Vincent.;
s.replace( 32, s2.length(), s2 );
std::cout << s << std::endl;
181
Insrer dans une chane
iterator string::insert( iterator it, const char&

ch );
string& string::insert( size_type index, const

string& str );
string& string::insert( size_type index,

const

char* str );
string& string::insert( size_type index1, const

string& str, size_type index2, size_type num );


string& string::insert( size_type index, const

char* str, size_type num );


string& string::insert( size_type index, size_type

num, char ch );
void string::insert( iterator it, size_type num,

const char& ch );
void string::insert( iterator it, iterator debut,

iterator fn );
Ces diffrentes versions de insert() permettent dinsrer
dans la chane courante :
le caractre ch avant la position indique par litrateur
it ;
la chane str lindice index ;
la sous-chane str (commenant lindice index2 et de
longueur num), lindice index1 ;
les num premiers caractres de str, lindice index ;
num fois le caractre ch, lindice index ;
num fois le caractre ch, avant la position indique par
litrateur it ;
les caractres de la squence [debut, fn[, avant la posi-
tion indique par litrateur it.
Inscrcr dans unc chanc
188 LhAPIJL 10 Lhancs dc caracIcrcs
Concatner des chanes
string& string::append( const string& str );
string& string::append( const char* str );
string& string::append( const string& str,

size_type index, size_type len );


string& string::append( const char* str, size_type

num );
string& string::append( size_type num, char ch );
string& string::append( input_iterator start,

input_iterator end );
Les diffrentes fonctions append() permettent dajouter
la fn de la chane courante :
la chane str ;
la sous-chane de str commenant lindice index et
de longueur len ;
les num premiers caractres de str ;
num fois le caractre ch ;
les caractres contenus dans la squence [debut, fn[.
Par exemple, le code ci-aprs utilise append() pour ajouter
dix points dexclamation une chane. Il affchera la chane
Bonjour le monde!!!!!!!!!! .
std::string str = Bonjour le monde;
str.append(10, !);
std::cout << str << std::endl;
180
Cet autre exemple ajoute une sous-chane une autre chane.
Il affchera str1 vaut : Une premire chane rallonge.
std::string str1 = Une premire chane...;
std::string str2 = qui peut tre rallonge...;
str1.append(str2, 16, 11);
std::cout << str1 vaut : << str1 << std::endl;
Effacer une partie dune chane
iterator string::erase( iterator it );
iterator string::erase( iterator debut, iterator fn );
string& string::erase( size_type index = 0, size_type

num = npos );
Les fonctions erase() permettent deffacer :
le caractre point par l'itrateur it, puis de renvoyer
litrateur sur le caractre suivant ;
les caractres de la sous-squence [debut, fn[, puis de
renvoyer litrateur pointant sur le caractre suivant le
dernier supprim ;
les num caractres partir de lindice index, puis de ren-
voyer une rfrence sur la chane elle-mme.
Les paramtres index et num ont des valeurs par dfaut et
peuvent tre omis. Si vous ne spcifez pas num, tous les
caractres aprs lindice index inclus seront supprims. Si
vous nindiquez aucun des deux, toute la chane sera
vide ; cest lquivalent dun clear().
Lffaccr unc parIc dunc chanc
100 LhAPIJL 10 Lhancs dc caracIcrcs
std::string s(Alors, on aime les beignets ? Il faut

beignetiser le monde entier !);


std::cout << La chane originale est << s << <<

std::endl;

s.erase( 50, 16 );
std::cout << Maintenant cest << s << << std::endl;
s.erase( 29 );
std::cout << Maintenant cest << s << << std::endl;
s.erase();
std::cout << Maintenant cest << s << << std::endl;
Le code ci-avant produira la sortie ci-aprs.
The original string is Alors, on aime les beignets ?

Il faut beignetiser le monde entier !


Maintenant cest Alors, on aime les beignets ? Il faut

beignetiser !
Maintenant cest Alors, on aime les beignets ?
Maintenant cest
Lire des lignes dans un fux
istream& getline(istream& is, string& s, char

delimiteur = \n );
La fonction getline() nest pas une fonction membre de
std::string<> mais une fonction globale. Elle lit une ligne
dans le fux is et stocke les caractres lus dans la chane s.
Lire une ligne consiste lire tous les caractres qui se pr-
sentent jusqu en rencontrer un gal au delimiteur.
101
Par exemple, le code suivant lit une ligne sur lentre stan-
dard et laffche sur la sortie standard :
std::string s;
std::getline( std::cin, s );
std::cout << Vous avez ecrit : << s << std::endl;
Aprs avoir rcupr le contenu dun fux dans une
chane, vous trouverez probablement utile dutiliser un
std::string_stream pour en extraire certains types dinfor-
mation. Par exemple, le code ci-aprs lit des nombres sur
lentre standard, tout en ignorant les lignes commentes
commenant par // .
string s;
while ( std::getline(std::cin,s) )
{
if ( s.size() >= 2 && s[0] == / && s[1] == / )
{
std::cout << * commentaire ignor : << s <<

std::endl;
}
else
{
std::istringstream ss(s);
double d;
while ( ss >> d )
{
std::cout << * un nombre : << d << std::

endl;
}
}
}
Lrc dcs |gncs dans un ux
102 LhAPIJL 10 Lhancs dc caracIcrcs
Avec ce code, vous pouvez, en entrant les mmes valeurs,
obtenir le rsultat suivant :
// test
* commentaire ignor : // test
22.3 -1 3.13149
* un nombre : 22.3
* un nombre : -1
* un nombre : 3.14159
// prochaine squence
* commentaire ignor : // prochaine squence
1 2 3 4 5
* un nombre : 1
* un nombre : 2
* un nombre : 3
* un nombre : 4
* un nombre : 5
50
* un nombre : 50
11
Fchcrs cI ux
La bibliothque standard (STL) dfnit, travers len-tte
<iostream>, une srie de fux dits standard :
std::cout est un objet de type std::ostream permettant
daffcher des donnes sur la sortie standard ;
std::cerr est un autre objet std::ostream permettant la
mme chose, mais sans mise en tampon ;
std::clog est la version avec mise en tampon de std::
cerr ;
std::cin est un objet de type std::istream permettant
de lire des donnes sur lentre standard.
Len-tte <fstream> contient tout le ncessaire pour effec-
tuer des oprations sur fchiers avec les classes std::ifs-
tream, pour la lecture, et std::ofstream, pour lcriture.
Certains comportements des fux dentre/sortie de la
bibliothque standard C++ (comme la prcision, la justi-
fcation, etc.) peuvent tre modifs grce aux divers mani-
pulateurs de fux.
104 LhAPIJL 11 Fchcrs cI ux
Ouvrir un fchier
#include <fstream>
std::fstream(const char* flename, openmode mode);
std::ifstream(const char* flename, openmode mode);
std::ofstream(const char* flename, openmode mode);
std::fstream::open(const char* flename, openmode

mode);
Ces trois classes permettent de manipuler des fchiers. Le
paramtre mode est optionnel. Vous trouverez les diffrentes
signifcations et possibilits dans le tableau ci-aprs. Elles
sutilisent de manire analogue aux fux prdfnis std::
cin et std::cout.
Mode douverture des fchiers
Modc 0cscrpIon
std::ios::app Ajouter la fn (append)
std::ios::ate Se placer la fn lors de louverture
std::ios::binary Ouvrir le fchier en mode binaire
std::ios::in Ouvrir le fchier en lecture
std::ios::out Ouvrir le fchier en criture
std::ios::trunc craser le fchier existant
std::ios::nocreate Unix seulement, ne cre pas le fchier
sil nexiste pas
AIIcnIon
Avec Microsoft, vous trouverez ces constantes dans ios_base
en lieu et place de ios.
105
Lexemple suivant ajoute le contenu dun fchier un autre :
char temp;
std::ifstream fn(fchier1.txt);
std::ofstream fout(fchier2.txt, std::ios::app);
while ( fn >> temp )
fout << temp;
fn.close();
fout.close();
Tester ltat dun fux
stream::operator bool();
bool stream::fail();
bool stream::good();
bool stream::bad();
bool stream::eof();
ios::iostate stream::rdstate();
La conversion implicite en boolen permet de tester ais-
ment si une erreur est survenue. Par ce biais, il est facile de
tester si louverture dun fchier sest bien droule. Le
code ci-aprs lillustre simplement. Si vous prfrez un
appel plus explicite, utilisez la fonction membre fail().
std::string nom_de_fchier = data.txt;
std::ifstream fchier( nom_de_fchier.c_str() );
if ( ! fchier )
std::cout << Erreur lors de louverture du fchier.\n;
La fonction membre good() permet de vrifer quaucune
erreur nest apparue. La fonction membre bad() permet
de tester si une erreur fatale est survenue. La fonction
membre eof() permet de tester simplement si la fn du
fchier est atteinte.
JcsIcr |cIaI dun ux
108 LhAPIJL 11 Fchcrs cI ux
Par exemple, le code ci-aprs lit des donnes sur le fux
dentre in et les crits sur le fux de sortie out pour enfn
utiliser eof() et vrifer quaucune erreur nest survenue.
char tampon[TAILLE];
do
{
in.read( tampon, TAILLE );
std::streamsize n = in.gcount();
out.write( tampon, n );
}
while ( in.good() );
if ( in.bad()
||
!in.eof() )
{
// une erreur fatale est survenue
}
in.close();
Enfn, la fonction membre rdstate() retourne ltat com-
plet du fux considr. Le tableau suivant donne la liste des
valeurs possibles.
tat dun fux
F|ag 0cscrpIon
std::ios::badbit Une erreur fatale est survenue
std::ios::eofbit Fin de fchier atteinte
std::ios::failbit Une erreur non critique est survenue
std::ios::goodbit Aucune erreur nest survenue
AIIcnIon
Avec Microsoft, vous trouverez ces constantes dans ios_base
en lieu et place de ios.
101
Lire dans un fchier
std::istream& operator >> (std::istream&, );
std::istream& std::istream::getline(char* tampon,

stringsize n);
std::istream& std::istream::getline(char* tampon,

stringsize n, char delim);


std::streamsize std::fstream::gcount();
int std::fstream::get();
std::istream& std::istream::get(char& ch);
std::istream& std::istream::get(char* tampon,

streamsize num);
std::istream& std::istream::get(char* tampon,

streamsize num, char delim);


std::istream& std::istream::get(streambuf& tampon);
std::istream& std::istream::get(streambuf& tampon,

char delim);
int std::fstream::peek();
std::istream& std::istream::read(char* buffer,

streamsize num);
Il existe plusieurs faons de lire dans un fux. La plus pra-
tique est dutiliser loprateur de redirection >>, car la
plupart des conversions sont alors faites automatiquement.
De plus, comme le montre lexemple ci-aprs, utiliser
conjointement cet oprateur avec le type chane permet
de lire un fchier mot par mot. La sparation des mots ne
correspond pas exactement au langage naturel. Elle se base
uniquement sur les caractres espace, tabulation et retour
chariot.
std::ifstream fn(donnees.txt);
std::string s;
while ( fn >> s )
std::cout << Mot lu : << s << std::endl;
Lrc dans un chcr
108 LhAPIJL 11 Fchcrs cI ux
Lexemple suivant montre comment lire un fchier ligne
par ligne :
std::ifstream fchier(donnees.txt);
const int TAILLE = 100;
char str[TAILLE];
while ( fchier.getline(str, TAILLE) )
std::cout << Ligne lue : << s << std::endl;
Si vous souhaitez viter le tableau de caractres la C,
vous pouvez utiliser la fonction std::getline() qui lit des
lignes et les stocke dans un std::string (voir la section
Lire des lignes dans un fux au Chapitre 10 pour de
plus amples explications).
std::ifstream fchier(donnees.txt);
std::string s;
while ( std::getline(fchier,s) )
std::cout << Ligne lue : << s << std::endl;
gcount() est utile pour connatre le nombre de caractres
effectivement lus lors de la dernire opration de lecture.
Les fonctions membres get() permettent de :
lire un caractre et retourner sa valeur ;
lire un caractre et le stocker dans la variable ch ;
lire jusqu' num-1 caractres (sarrte si la fn du fchier
ou un retour chariot ou le caractre delim est atteint) ;
lire tous les caractres jusqu' la fn, le prochain retour
chariot ou le caractre delim, et les stocker dans le
tampon donn.
char ch;
std::ifstream fchier(donnees.txt);
while (fchier.get(ch))
std::cout << ch;
fchier.close();
100
La fonction membre peek() retourne le prochain caractre
du fux, sans pour autant le retirer de celui-ci.
Enfn, la fonction membre read() permet de lire num octets
(et pas caractres) dans le fux et de les placer dans le
tampon donn. Si la fn de fchier est atteinte avant, la lec-
ture sarrte et les octets lus sont placs dans le tampon.
struct Rectangle { int h,w; };
//
fchier.read(reinterpret_cast<char*>(&rect),

sizeof(Rectangle));
if (fchier.bad())
{
std::cerr << Erreur lors de la lecture des donnes\n;
exit(0);
}
AsIucc : gnorcr unc parIc dun ux
std::istream& std::istream::ignore(streamsize num=1,

int delim=EOF);
La fonction membre ignore() sutilise avec les fux dentre.
Elle lit et ignore jusqu num caractres ou moins si le caractre
delim est rencontr avant. Par dfaut, num vaut 1 et delim
correspond la fn du fchier.
Cette fonction peut parfois savrer utile lorsque lon utilise
conjointement la fonction getline() et loprateur >>. Par
exemple, si vous lisez une entre fnissant par une fn de ligne
avec loprateur >>, le retour chariot reste prsent dans le fux.
Comme getline() sarrte par dfaut sur le prochain retour
chariot, le prochain appel cette fonction renverra une chane
vide. Dans ce cas, la fonction ignore() peut tre appele avant
getline() pour dbarrasser le fux du retour chariot gnant.
Lrc dans un chcr
200 LhAPIJL 11 Fchcrs cI ux
crire dans un fchier
std::ostream& std::ostream::put( char ch );
std::ostream& std::ostream::write(const char*

tampon, streamsize num )


std::ostream& std::ostream::fush();
std::ostream& operator << (std::ostream&, );
std::istream& std::istream::putback(char ch);
La fonction membre put() crit le caractre ch dans le
fux. La fonction membre write() crit les num premiers
octets du tampon donn dans le fux.
La fonction fush() force lcriture des tampons internes
du fux. Ceci est particulirement utile pour lcriture
dinformation de dbogage : dans certains cas de plantage,
une partie des donnes crites dans un fux de fchiers
peut ne pas avoir t transfre sur le disque mais tre
reste en mmoire, et donc perdue. Un appel judicieux
fush() assure le transfert du tampon interne vers le pri-
phrique li au fux.
Pour les fux en mode texte, vous disposez de nombreux
oprateurs >> sur tous les types de base du C++. Il est
mme possible, la printf(), de prciser comment for-
mater les donnes crire. Reportez-vous la section
Manipuler des fux un peu plus loin dans ce chapitre.
La fonction membre putback(), contrairement ce que
lintitul de cette section pourrait laisser penser, sutilise
sur les fux de lecture. Elle permet de simuler un retour
en arrire en remettant le caractre ch dans le fux,
comme si on ne lavait pas encore lu. Pour ceux qui
connaissent la bibliothque C, elle correspond la fonc-
tion C int ungetc(int ch, FILE*).
201
Se dplacer dans un fux
std::istream& std::istream::seekg( std::off_type

offset, std::ios::seekdir origine );


std::istream& std::istream::seekg( std::pos_type

position );
std::pos_type std::istream::tellg();
std::ostream& std::ostream::seekp( std::off_type

offset, std::ios::seekdir origine );


std::ostream& std::ostream::seekp( std::pos_type

position );
std::pos_type std::ostream::tellp();
Les fonctions membres seekg() permettent de dplacer le
curseur de lecture dun fux dentre, soit la position
offset relative lorigine donne, soit la position abso-
lue fournie. Le prochain appel de get() partira de ce
nouvel emplacement.
La fonction membre tellg() permet de connatre la posi-
tion actuelle dans le fux de lecture.
Position relative dans un fux
va|cur 0cscrpIon
std::ios::beg Dcalage relatif au dbut du fchier
std::ios::cur Dcalage relatif la position courante
std::ios::end Dcalage relatif la fn du fchier
Les fonctions membres seekp() et tellp() sont les quivalen-
tes des prcdentes, mais pour les fux dcriture (ou de sortie).
Sc dcp|accr dans un ux
202 LhAPIJL 11 Fchcrs cI ux
Lexemple suivant affche la position courante dun fux de
fchier et laffche sur la sortie standard :
std::string s(Une chane de caractres quelconque...);
std::ofstream fchier(sortie.txt);
for (int i=0; i < s.length(); ++i)
{
std::cout << Position : << fchier.tellp();
fchier.put( s[i] );
std::cout << << s[i] << std::endl;
}
fchier.close();
Manipuler des fux
std::fmtfags std::stream::fags();
std::fmtfags std::stream::fags( fmtfags f )
std::fmtfags std::stream::setf( fmtfags fags );
std::fmtfags std::stream::setf( fmtfags fags,

fmtfags needed );
void std::stream::unsetf( fmtfags fags );
Les fonctions membres fags() retournent le masque de
formatage des donnes du fux courant, ou permettent de
le changer. Vous retrouverez les diffrentes valeurs de ce
masque dans le tableau ci-aprs.
Les fonctions membres setf() permettent dactiver des
options de formatage (fags). Le paramtre needed permet
de ne changer que les options communes. La valeur retour-
ne est ltat avant changement. La fonction membre unsetf()
permet au contraire de dsactiver loption spcife.
208
int nombre = 0x3FF;
std::cout.setf( std::ios::dec );
std::cout << Dcimal : << nombre << std::endl;
std::cout.unsetf( std::ios::dec );
std::cout.setf( std::ios::hex );
std::cout << Hxadcimal : << nombre << std::endl;
Grce aux manipulateurs, le code prcdent peut tre rem-
plac par le code suivant, qui est beaucoup plus simple :
int nombre = 0x3FF;
std::cout << Dcimal : << std::dec << nombre
<<

std::endl
<< Hexadcimal : << std::hex << nombre
<< std::endl;
Manipulateurs de fux
Manpu|aIcur 0cscrpIon LnIrcc SorIc
boolalpha Affche les boolens sous forme
textuelle (true et false) X X
dec Passe en mode dcimal X X
endl crit un caractre de fn
de ligne, vide le tampon _ X
ends crit un caractre nul _ X
fxed Affche les nombres rels en mode
standard (par opposition scientifque) _ X
fush Vide le tampon interne du fux _ X
hex Passe en mode hexadcimal X X
internal Si un nombre est complt
pour remplir une taille donne,
des espaces sont insrs entre le
signe et le symbole de la base _ X
left Justife le texte gauche _ X
Manpu|cr dcs ux
204 LhAPIJL 11 Fchcrs cI ux
Manipulateurs de fux (suite)
Manpu|aIcur 0cscrpIon LnIrcc SorIc
noboolalpha
Naffche pas les boolens
X X

sous forme textuelle
noshowbase
Naffche pas le prfxe
_ X

servant de symbole de la base
noshowpoint
Dsactive laffchage forc
_ X

de la virgule et des zros
inutiles des nombres rels
noshowpos
Dsactive laffchage forc
_ X
du + devant les nombres positifs
noskipws Pour ne plus ignorer les blancs X _
nounitbuf Dsactive le mode initbuf _ X
nouppercase
Affche le e de la notation
_ X

scientifque et le x de la notation
hexadcimale en minuscule
oct Passe en mode octal X X
right Passe en alignement droite _ X
scientifc
Affche les rels en
_ X

mode scientifque
showbase
Affche le prfxe, symbole
_ X

de la base utilise
showpoint
Affche toujours le point
_ X
des nombres rels
showpos
Affcher toujours un plus
devant les nombres positifs
_ X
skipws Passe en mode ignorer les blancs X _
unitbuf
Force lcriture (vide le tampon)
aprs chaque insertion
_ X
uppercase
Passe en mode majuscules forces
_ X
pour le e de la notation scientifque
et le x de la notation hexadcimale
ws Saute les blancs restant X _
205
Manipulateurs dfnis dans <iomanip>
Manpu|aIcur 0cscrpIon LnIrcc SorIc
resetiosfags(int long) Met off le fag spcif X X
setbase(int base)
Prcise la base utiliser
_ X
pour laffchage
setfll(int ch)
Prcise le caractre
_ X

utiliser pour le remplissage
setiosfags(long f) Met on le fag spcif X X
setprecision(int p)
Fixe le nombre de chiffres
_ X

aprs la virgule
setw(int w)
Fixe la largeur pour les
_ X

fonctions dalignement
Manipuler une chane de
caractres comme un fux
#include <sstream>
std::stringstream::stringstream( [ std::string s [,

std::openmode mode ]] );
void std::stringstream::str(std::string s);
std::string std::stringstream::str();
Les fux de chanes de caractres sutilisent de manire
analogue aux fux de fchiers. Le paramtre mode est le
mme que pour ces derniers.
Manpu|cr unc chanc dc caracIcrcs commc un ux
208 LhAPIJL 11 Fchcrs cI ux
crire dans une chane de
caractre comme dans un fux
std::ostringstream::ostringstream( [ std::string s

[, std::openmode mode ]] );
Un objet std::ostringstream peut tre utilis pour crire
le contenu dune chane. Cest un peu le pendant de la
fonction C sprintf().
std::ostringstream s_fux;
int i = 3;
s_fux << Coucou puissance << i << std::endl;
std::string str = s_fux.str();
std::cout << str;
Lire le contenu dune chane
comme avec un fux
std::istringstream::istringstream( [ std::string s

[, std::openmode mode ]] );
Un objet std::istringstream permet de lire le contenu
dune chane, un peu comme le sscanf() du C.
std::istringstream fux_chaine;
std::string chaine = 33;
fux_chaine.str(chaine);
int i;
fux_chaine >> i;
std::cout << i << std::endl; // affche 33
201
Vous pouvez aussi spcifer directement sur quelle chane
travailler en la fournissant au constructeur :
std::string chaine = 33;
std::istringstream fux_chaine(chaine);
int i;
fux_chaine >> i;
std::cout << i << std::endl; // affche 33
Un objet std::stringstream permet deffectuer la fois
des oprations de lecture et dcriture, comme pour les
objets std::fstream.
Lrc |c conIcnu dunc chanc commc avcc un ux
12
A|gorIhmcs
sIandard
La bibliothque standard (STL) fournit de nombreux
algorithmes utilisables sur ses conteneurs ou tous conte-
neurs compatibles. Ce chapitre vous permettra den
exploiter tout le potentiel.
Algorithmes standard
Nom 0cscrpIon Pagc
accumulate
Calculer la somme des lments
dune squence
214
adjacent_difference
Calculer les diffrences entre lments
conscutifs dune squence
215
adjacent_fnd
Chercher la premire occurrence de
deux lments conscutifs identiques
217
binary_search
Rechercher un lment dans une
squence
218
copy
Copier les lments dune squence
dans une autre
219
copy_backward
Copier les lments dune squence dans
une autre en commenant par la fn
221
copy_n
Copier les n premiers lments
dune squence dans une autre
222
210 LhAPIJL 12 A|gorIhmcs sIandard
Algorithmes standard (Suite)
Nom 0cscrpIon Pagc
count
Compter le nombre dlments
correspondant une valeur donne
223
count_if
Compter le nombre dlments
conformes un test donn
224
equal Tester si deux squences sont identiques 225
equal_range
Chercher la sous-squence dlments
tous gaux un certain lment
226
fll Initialiser une squence avec une valeur 228
fll_n
Initialiser les n premiers lments dune
squence avec une valeur
228
fnd
Chercher le premier lment gal
une valeur dans une squence
228
fnd_end
Chercher la dernire apparition
dune sous-squence donne
266
fnd_frst_of
Chercher le premier lment dont la
valeur est prsente dans un ensemble
donn
229
fnd_if
Chercher le premier lment vrifant
un test donn
228
for_each
Appliquer une fonction/foncteur sur
tous les lments dune squence
230
generate
Initialiser une squence laide
dun gnrateur de valeurs
231
generate_n
Initialiser les n premires valeurs dune
squence avec un gnrateur de valeurs
231
includes
Dterminer si tous les lments
dune squence sont dans une autre
232
inner_product
Calculer le produit intrieur (produit
scalaire gnralis) de deux squences
234
inplace_merge
Fusionner deux squences tries
(dans la premire)
243
iota
Initialiser les lments dune squence
avec une valeur (en lincrmentant)
235
211
Algorithmes standard (Suite)
Nom 0cscrpIon Pagc
is_heap Tester si la squence est un tas 236
is_sorted Tester si une squence est trie 274
iter_swap
changer le contenu des deux
variables pointes
275
lexicographical_
compare
Tester si une squence est lexicographi-
quement plus petite quune autre
238
lexicographical_
compare_3way
Tester si une squence est lexicographi-
quement plus petite (1), gale (0), ou
suprieure (1) quune autre
238
lower_bound
Chercher le premier endroit o insrer
une valeur sans briser lordre de la
squence
241
make_heap Transformer la squence en tas 236
max
Rcuprer le plus grand lment
(entre deux)
245
max_element
Rcuprer le plus grand lment
dune squence
246
merge
Fusionner deux squences tries
(dans une troisime)
243
min
Rcuprer le plus petit lment
(entre deux)
245
min_element
Rcuprer le plus petit lment
dune squence
246
mismatch
Trouver le premier endroit o
deux squences diffrent
247
next_permutation
Gnrer la prochaine plus grande permu-
tation lexicographique dune squence
248
nth_element
Faire en sorte que le nime lment soit
le mme que si la squence tait trie et
assurer quaucun lment sa gauche ne
soit plus grand quun sa droite
250
partial_sort
Trier les n premiers lments dune
squence
251
A|gorImcs sIandard
212 LhAPIJL 12 A|gorIhmcs sIandard
Nom 0cscrpIon Pagc
partial_sort_copy
Copier les n plus petits lments
dune squence (le rsultat est tri)
252
partial_sum
Calculer la somme partielle gnralise
dune squence
253
partition
Couper une squence en deux en
fonction dun prdicat (ne prserve
pas forcment lordre des lments
identiques)
254
pop_heap Retirer le plus grand lment dun tas 236
power
Calculer xi (fonction puissance
gnralise)
256
prev_permutation
Gnrer la prochaine plus petite permu-
tation lexicographique dune squence
248
push_heap Ajouter un lment un tas 236
random_sample
Copier alatoirement un chantillon
dune squence (nombre dlments
dtermins par la taille de la squence
rsultat)
257
random_sample_n
Copier alatoirement un sous-chantillon
(de n lments) dune squence, en
prservant leur ordre dorigine
258
random_shuffe Mlanger les lments dune squence 259
remove
Supprimer les lments gaux une
valeur donne
260
remove_copy
Copier une squence en omettant les
lments gaux une valeur donne
262
remove_copy_if
Copier une squence en omettant
les lments vrifant un test donn
262
remove_if
Supprimer les lments vrifant
un test donn
260
replace
Remplacer tous les lments gaux
une valeur par une autre
263
Algorithmes standard (Suite)
218
Nom 0cscrpIon Pagc
replace_copy
Copier une squence en remplaant
certaines valeurs par une autre
263
replace_copy_if
Copier une squence en remplaant
certaines valeurs vrifant un test par
une autre
263
replace_if
Remplacer tous les lments respectant
un test donn par une nouvelle valeur
263
reverse Inverser lordre de la squence 264
reverse_copy
Copier une squence en inversant
son ordre
264
rotate
Effectuer une rotation des lments
de la squence
264
rotate_copy
Copier une squence en effectuant une
rotation des lments de la squence
264
search
Chercher la premire apparition dune
sous-squence donne
265
search_n
Chercher la premire apparition de
n occurrences conscutives dune valeur
donne
265
set_difference
Construire la diffrence de deux
squences tries
268
set_intersection
Construire lintersection de deux
squences tries
270
set_symmetric_
difference
Construire la diffrence symtrique de
deux squences tries
272
set_union
Construire lunion de deux squences
tries
273
sort
Trier une squence (ne prserve pas
forcment lordre des lments identiques)
274
sort_heap Transformer un tas en squence trie 236
stable_partition
Couper une squence en deux en
fonction dun prdicat (prserve lordre
des lments identiques)
254
A|gorImcs sIandard
Algorithmes standard (Suite)
214 LhAPIJL 12 A|gorIhmcs sIandard
Nom 0cscrpIon Pagc
stable_sort
Trier une squence (prserve lordre
des lments identiques)
274
swap changer le contenu de deux variables 275
swap_ranges
changer le contenu de deux
squences de mme taille
275
transform
Transformer une (ou deux)
squences en une autre
276
unique Supprimer les doublons dune squence 278
unique_copy
Copier une squence en supprimant
les doublons dune squence
278
upper_bound
Chercher le dernier endroit o insrer
une valeur sans briser lordre de la
squence
241
uninitialized_copy
Copier laide du constructeur
par copie
281
uninitialized_copy_n
Copier laide du constructeur
par copie (n lments)
281
uninitialized_fll
Initialiser laide du constructeur
par copie
282
uninitialized_fll_n
Initialiser laide du constructeur
par copie (n lments)
282
Calculer la somme des lments
dune squence
#include <numeric>
TYPE accumulate(InputIterator debut, InputIterator

fn, TYPE init);


TYPE accumulate(InputIterator debut, InputIterator

fn, TYPE init, BinaryFunction f);


215
La fonction accumulate() calcule la somme de init plus
tout les lments de lensemble [debut, fn[. Si la fonction
binaire f est fournie, elle sera utilise la place de lopra-
teur +.
La complexit est en temps linaire O(n) fois la complexit
de loprateur utilis.
std::list<double> l;
double moyenne = std::accumulate(l.begin(), l.end(), 0.0)

/ l.size();
double produit = std::accumulate(l.begin(), l.end(), 1.0,

std::multiplies<double>());
Calculer les diffrences
entre lments conscutifs
dune squence
#include <numeric>
TYPE adjacent_difference(InputIterator debut,

InputIterator fn, OutputIterator resultat);


TYPE adjacent_difference(InputIterator debut,

InputIterator fn, OutputIterator resultat,

BinaryFunction f);
La fonction adjacent_difference() calcule la diffrence
des lments adjacents de lensemble [debut, fn[. Si len-
semble en entre contient les lments (a, b, c, d), le rsul-
tat sera (a, b-a, c-b, d-c). Si la fonction binaire f est fournie,
elle sera utilise la place de loprateur -.
La|cu|cr |cs dffcrcnccs cnIrc c|cmcnIs consccuIfs dunc scqucncc
218 LhAPIJL 12 A|gorIhmcs sIandard
Info
La sauvegarde dans le rsultat du premier lment en entre
nest pas inutile. Elle permet davoir suffsamment dinforma-
tion pour reconstruire la squence dorigine. En particulier,
avec les oprateurs arithmtiques que sont laddition et la
soustraction, adjacent_difference et partial_sum sont
la rciproque lune de lautre.
std::vector<int> v1;
// initialisation de v1 avec des valeurs ...
std::vector<int> v2(v1.size());

std::cout << V1 : ;
std::copy(v1.begin(), v1.end(), std::ostream_iterator

<int>(std::cout, ));
std::cout << std::endl;

std::adjacent_difference(v1.begin(), v1.end(), v2.

begin());
std::cout << Diffrences : ;
std::copy(v2.begin(), v2.end(), std::ostream_iterator

<int>(std::cout, ));
std::cout << std::endl;

std::cout << Reconstruction : ;
std::partial_sum(v2.begin(), v2.end(),

std::ostream_ iterator<int>(std::cout, ));


std::cout << std::endl;

211
Chercher la premire occurrence
de deux lments conscutifs
identiques
#include <algorithm>
ForwardIterator adjacent_fnd(ForwardIterator debut,

ForwardIterator fn);
ForwardIterator adjacent_fnd(ForwardIterator debut,

ForwardIterator fn, BinaryPredicate pred);


La fonction adjacent_fnd() renvoie le premier itrateur i
tel que *i == *(i+1) et tel que les itrateurs i et i+1 appar-
tiennent la squence [debut, fn[ donne. Si un tel itra-
teur nexiste pas, la fonction renvoie fn. Si le prdicat
binaire pred est fourni, il sera utilis la place de lopra-
teur ==.
Par exemple, si v est un vecteur dentier contenant les
valeurs (1, 2, 3, 3, 4, 5, 6, 7, 8). Le code suivant permet de
reprer lemplacement de la paire de 3 :
std::vector<int>::iterator it = adjacent_fnd(v.begin(),

v.end());
if (it == v.end())
std::cout << Pas dlments contigus gaux dans

v\n;
else
std::cout << Deux lments contigus trouvs, de

valeur :
<< *it << std::endl;
Lhcrchcr |a prcmcrc occurrcncc dc dcux c|cmcnIs consccuIfs dcnIqucs
218 LhAPIJL 12 A|gorIhmcs sIandard
Rechercher un lment
dans une squence
#include <algorithm>
bool binary_search(ForwardIterator debut,

ForwardIterator fn, const LessThanComarable& val);


bool binary_search(ForwardIterator debut,

ForwardIterator fn, const TYPE& val,

StrickWeakOrdering comp);
La fonction binary_search() recherche la valeur val dans
[debut, fn[. Les lments dans lensemble de recherche doi-
vent imprativement tre tris en ordre croissant (relative-
ment loprateur <).
Si val est trouv, la fonction renvoie true, sinon elle ren-
voie false.
Si une fonction de comparaison comp est fournie, elle sera
utilise pour comparer les lments. Bien videmment, les
lments de lensemble de recherche doivent tre tris
daprs ce comparateur.
Cette recherche est logarithmique pour les itrateurs de type
RandomAccessIterator, quasi linaire sinon (logarithmique
pour les comparaisons, linaire pour le nombre dtapes).
AIIcnIon
Cette recherche binaire ne fonctionne que si lensemble dans
lequel est effectue la recherche est tri.
Loprateur de comparaison comp est une relation dordre strict
(au sens mathmatique du terme). Cest--dire que si a comp b
est vrai, alors b comp a est faux. galement, si a comp b et
b comp c sont vrais, alors a comp c est vrai. Enfn si a comp b
et b comp a sont faux tous les deux, alors a et b sont quiva-
lents (gaux).
210
Le code suivant teste la prsence des nombres 0 9 dans
un tableau :
for (int i=0 ; i<10 ; i++)
{
if (binary_search(tab.begin(), tab.end(), i))
std::cout << i << est dans le tableau\n ;
else
std::cout << i << NEST PAS dans le tableau\n ;
}
Si le tableau en entre vaut {23, 12, 0, 1, 2, 4, 5, 6, 8, 9,
50, 100, 300}, vous obtiendrez :
0 est dans le tableau
1 est dans le tableau
2 est dans le tableau
3 NEST PAS dans le tableau
4 est dans le tableau
5 est dans le tableau
6 est dans le tableau
7 NEST PAS dans le tableau
8 est dans le tableau
9 est dans le tableau
Copier les lments dune
squence dans une autre
#include <algorithm>
OutputIterator copy(InputIterator debut,

InputIterator fn, OutputIterator resultat);


La fonction copy() copie un par un les lments de [debut,
fn[ dans resultat. Le rsultat fnal se situe dans [resultat,
resultat + (fn debut) [. Gnralement, la copie est
Lopcr |cs c|cmcnIs dunc scqucncc dans unc auIrc
220 LhAPIJL 12 A|gorIhmcs sIandard
effectue par lopration *(result + n) = *(frst + n)
pour n allant de 0 fn - debut, dans lordre croissant.
std::vector<int> source(10), dest(10);
// initialisation de la source
std::iota(source.begin(), source.end(), 1);
// copie les lments de source dans dest
std::copy(source.begin(), source.end(), dest.begin());
Vous pouvez aussi utiliser lalgorithme de copie pour
crire le contenu dune squence sur la sortie standard trs
simplement. Lexemple suivant lillustre, tout en sparant
les lments crits par un espace :
// #include <iomanip> pour ostream_iterator
std::copy(source.begin(), source.end(),

std::ostream_iterator<int>(std::cout, ));
AIIcnIon
Litrateur resultat doit pointer sur une squence mmoire
valide.
cause de lordre de la copie, litrateur resultat ne doit pas
tre dans la squence [debut, fn[. Par contre, la fn de la squence
rsultat peut avoir une partie commune avec la squence source.
Lalgorithme copy_backward a la restriction oppose.
221
Copier les lments dune
squence dans une autre
en commenant par la fn
#include <algorithm>
BidirectionalIterator2 copy_backward

(BidirectionalIterator1 debut,

BidirectionalIterator1 fn, BidirectionalIterator2

resultat);
Cette fonction est presque la mme que la prcdente
(copy()). La diffrence rside dans lordre de la copie. copy_
backward() commence par le dernier et fnit par le premier
lment (sans inverser la squence).
Ainsi, la fonction copy_backward() copie un par un les l-
ments de [debut, fn[ dans resultat. Le rsultat fnal se situe
dans [resultat - (fn - debut), resultat[. Gnralement, la
copie est effectue par lopration *(result - n - 1) =
*(frst - n) pour n allant de 0 fn - debut, dans lordre
croissant. La copie est donc faite depuis le dernier jusquau
premier lment de la squence.
Lexemple suivant copie les dix premiers lments dun
vecteur la fn de celui-ci :
std::copy_backward( vec.begin(), vec.begin() + 10,

vec.end() );
AIIcnIon
Litrateur resultat doit pointer sur une squence mmoire
[resultat (fn debut), resultat[ valide.
cause de lordre de la copie, litrateur resultat ne doit pas
tre dans la squence [debut, fn[. Par contre, le dbut de la
squence de rsultat peut avoir une partie commune avec la
squence source. Lalgorithme copy() a la restriction oppose.
Lopcr |cs c|cmcnIs dunc scqucncc dans unc auIrc cn commcnanI par |a n
222 LhAPIJL 12 A|gorIhmcs sIandard
Copier les n premiers lments
dune squence dans une autre
#include <algorithm>
OutputIterator copy_n(InputIterator debut, Size n,

OutputIterator resultat);
La fonction copy_n() copie les lments de la squence
[debut, debut + n[ dans [resultat, resultat +n[. Gnralement,
la copie est faite par lopration *(resultat + i) = *(debut
+i) pour i allant de 0 n non inclus, dans lordre croissant.
std::vector<int> V(5);
std::iota(V.begin(), V.end(), 1);

std::list<int> L(V.size());
std::copy_n( V.begin(), V.size(), L.begin());
AIIcnIon
Size doit tre de type entier et n doit tre positif. Les squen-
ces [debut, debut + n[ et [resultat, resultat + n[ doivent
tre valides. Litrateur resultat ne doit pas faire partie de
la squence source. La mme restriction que celle de copy
sur la superposition des squences source et rsultat doit tre
respecte.
Info
Cette fonction peut paratre redondante avec copy. Contrai-
rement cette dernire, copy_n permet dutiliser des itra-
teurs de type input iterator et pas seulement forward iterator.
228
Compter le nombre dlments
correspondant une valeur
donne
#include <algorithm>
iterator_traits<InputIterator>::difference_type

count(InputIterator debut, InputIterator fn,

const EqualityComparable& valeur);


void count(InputIterator debut, InputIterator fn,

const EqualityComparable& valeur, Size& n);

// (ancien)
La fonction count() compte le nombre dlments de la
squence [debut, fn[ tant gaux valeur. Plus exactement,
la premire fonction retourne le nombre ditrateurs i de
[debut, fn[ tels que *i == valeur. La seconde ajoute ce
nombre n.
Info
La deuxime version est celle que lon trouve dans la STL dori-
gine, elle est conserve dans certaines implmentations mais
est susceptible dtre enleve tout moment. Seule la premire
version fait partie du standard C++.
Voici un exemple simple illustrant lutilisation de la STL
avec des types C :
int A[] = { 4, 3, 8, 0, 2, 5, 7, 0, 3, 8, 5, 6 };
const int N = sizeof(A) / sizeof(int);
std::cout << Il y a << std::count(A, A+N, 0) <<

zro(s).\n ;
LompIcr |c nomhrc dc|cmcnIs corrcspondanI a unc va|cur donncc
224 LhAPIJL 12 A|gorIhmcs sIandard
Compter le nombre dlments
conformes un test donn
#include <algorithm>
iterator_traits<InputIterator>::difference_type

count_if(InputIterator debut, InputIterator fn,

const UnaryPredicate& pred);


void count_if(InputIterator debut, InputIterator

fn, const UnaryPredicate& pred, Size& n);

// (ancien)
La fonction count_if() compte le nombre dlments de
la squence [debut, fn[ qui respectent le prdicat unaire
pred. Plus exactement, la premire fonction retourne le
nombre ditrateurs i de [debut, fn[ tels que pred(*i) est
vrai. La seconde (ancienne et pas toujours implmente)
ajoute ce nombre n.
Lexemple suivant compte tous les nombres pairs :
int A[] = { 4, 3, 8, 0, 2, 5, 7, 0, 3, 8, 5, 6 };
const int N = sizeof(A) / sizeof(int);
std::cout << Il y a << std::count_if(A, A+N,

std::compose1(std::bind2nd(std::equal_to<int>(),0),

std::bind2nd(std::modulus<int>(),2)))

<< nombre(s) pair(s).\n;


225
Info
Les nouvelles interfaces de count utilisent les classes itera-
tor_traits, qui reposent sur une particularit du C++ connue
sous le nom de spcialisation partielle. La plupart des compi-
lateurs nimplmentent pas la totalit de la norme ; ce faisant,
mme des compilateurs relativement rcents nimplmentent
pas toujours la spcialisation partielle. Si tel est le cas, la nou-
velle version de count ne sera pas forcment prsente ( moins
quelle retourne un size_t) ; de mme que les autres parties
de la STL utilisant les iterator_traits.
Tester si deux squences
sont identiques
#include <algorithm>
bool equal(InputIterator1 debut1, InputIterator1

fn1, InputIterator2 debut2);


bool equal(InputIterator1 debut1, InputIterator1

fn1, InputIterator2 debut2, BinaryPredicate pred);


La fonction equal() retourne vrai si les deux squences
[debut1, fn1[ et [debut2, debut2 + (fn1 debut1)[ sont
gales en les comparant lment par lment. La premire
version utilise la comparaison *i == *(debut2 + (i
debut1)), et la seconde pred(*i1,* (debut2 + (i debut1)))
== true, pour tout i appartenant la premire squence.
Lexemple suivant compare deux vector de mme taille :
bool egaux = std::equal(v1.begin(), v1.end(), v2.begin());
JcsIcr s dcux scqucnccs sonI dcnIqucs
228 LhAPIJL 12 A|gorIhmcs sIandard
Chercher la sous-squence
dlments tous gaux
un certain lment
#include <algorithm>
pair<ForwardIterator,ForwardIterator>

equal_range(ForwardIterator debut,

ForwardIterator fn, const LessThanComparable&

valeur);
pair<ForwardIterator,ForwardIterator> equal_range

(ForwardIterator debut, ForwardIterator fn,

const T& valeur, StricWeakOrdering comp);


La fonction equal_range() est une variante de binary_
search() : elle renvoie la sous-squence [debut, fn[ dont les
lments sont tous quivalents (voir la note ci-aprs)
valeur. La premire utilise loprateur de comparaison <, la
deuxime la relation dordre stricte comp.
Info
La relation dordre utilise doit tre stricte, mais pas ncessai-
rement totale. Il peut exister des valeurs x et y telles que les
tests x < y, x > y (plus exactement y < x) et x == y soient
tous faux. Trouver une valeur dans la squence ne revient
donc pas trouver un lment qui soit gal valeur mais
quivalent : ni infrieur, ni suprieur valeur. Si vous utilisez
une relation dordre totale, lquivalence et lgalit reprsen-
tent la mme chose. Cest le cas par exemple pour la compa-
raison dentiers ou de chanes de caractres avec strcmp.
221
AIIcnIon
equal_range() ne doit tre utilis que sur une squence trie
avec la mme relation dordre, ou selon une relation dordre
compatible .
Cette fonction peut tre vue comme une combinaison
des fonctions lower_bound() et upper_bound(). Ce sont en
effet ces valeurs que lon retrouve dans la paire retourne
par equal_range(). Mais cest plus rapide que dinvoquer
les deux fonctions prcites.
Pour bien comprendre ce que fait cette fonction, considrez
son utilisation ci-aprs, en postulant que le vecteur v uti-
lis contienne les valeurs 78, 34, 6, 2, 5, 5, 5, 5, 6, 12.
std::pair<std::vector<int>::iterator, std::vector

<int>::iterator> res;
res = std::equal_range(v.begin(), v.end(), 5);
std::cout << Le premier emplacement pour insrer 5

est avant << *res.frst << et le dernier (o il

peut tre insr avant) est << *res.second << .\n;


Vous obtiendrez la phrase Le premier emplacement pour
insrer 5 est avant 5 et le dernier (o il peut tre insr
avant) est 6. Bien entendu, le 5 o lon peut insrer avant
est le premier de la liste.
Info
equal_range() peut retourner une squence vide (une paire
contenant deux fois le mme itrateur). Cest le cas ds que la
squence dentre ne contient aucun lment quivalent
la valeur recherche. Litrateur renvoy est alors la seule
position o la valeur donne peut tre insre sans violer la
relation dordre.
Lhcrchcr |a sous-scqucncc dc|cmcnIs Ious cgaux a un ccrIan c|cmcnI
228 LhAPIJL 12 A|gorIhmcs sIandard
Initialiser une squence
#include <algorithm>
void fll(ForwardIterator debut, ForwardIterator

fn, const T& valeur);


OutptIterator fll_n(OutputIterator debut,

Size n, const T& valeur);


fll() affecte tous les lments de la squence [debut, fn[
la valeur donne. fll_n() le fait sur la squence [debut,
debut + n[ puis retourne debut + n.
std::vector<int> v(5);
std::vector<int>::iterator res;
std::fll(v.begin(), v.end(), -2); // v = -2, -2, -2, -2, -2
res = std::fll_n(v.begin(), 3, 0); // v = 0, 0, 0, -2, -2
*res = 1; // v = 0, 0, 0, 1, -2
Chercher le premier lment
tel que
#include <algorithm>
InputIterator fnd(InputIterator debut, InputIterator

fn, const EqualityComparable& value);


InputIterator fnd_if(InputIterator debut,

InputIterator fn, Predicate pred);


fnd() retourne le premier itrateur de la squence [debut,
fn[ tel que *i == value. Lalgorithme fnd_if() utilise
pred(*i)==true. Si aucun lment ne valide le test, la valeur
de retour est fn.
Lexemple suivant renvoie un itrateur sur le premier l-
ment positif dune liste dentiers :
220
res = std::fnd_if(L.begin(), L.end(),std::bind2nd

(greater<int>, 0));
Celui-ci cherche la premire occurrence de 7 :
res = std::fnd(L.begin(), L.end(), 7);
Chercher le premier lment
parmi
#include <algorithm>
InputIterator fnd_frst_of(InputIterator debut1,

InputIterator fn1, ForwardIterator debut2,

ForwardIterator fn2);
InputIterator fnd_frst_of(InputIterator debut1,

InputIterator fn1, ForwardIterator debut2,

ForwardIterator fn2, BinaryPredicate comp);


fnd_frst_of() est un peu comme fnd() en ce sens quil
recherche linairement travers la squence dentre
[debut1, fn1[. La diffrence tient au fait que fnd() cherche
une valeur donne dans la squence, alors que fnd_frst_
of() recherche nimporte quelle valeur apparaissant dans
la deuxime squence [debut2, fn2[. Ainsi, fnd_forst_of()
retourne litrateur pointant sur la premire valeur de
[debut1, fn1[ appartenant [debut2, fn2[, ou fn1 sinon.
La premire version de fnd_frst_of() utilise loprateur ==
pour comparer les lments. La deuxime utilise le prdi-
cat comp fourni.
Par exemple, essayez la fonction ci-aprs sur ces chanes
de caractres : Une phrase avec plusieurs mots. ou
UnSeulMot.
Lhcrchcr |c prcmcr c|cmcnI parm
280 LhAPIJL 12 A|gorIhmcs sIandard
char* premier_separateur(char* chaine, const int taille)
{
const char* blanc = \t\n ;
return std::fnd_frst_of(chaine, chaine+taille,

blanc, blanc+4);
}
Appliquer une fonction/foncteur
sur tous les lments dune
squence
#include <algorithm>
UnaryFunction for_each(InputIterator debut,

InputIterator fn, UnaryFunction f);


for_each() applique la fonction f sur tous les lments de
la squence [debut, fn[. Si f retourne une valeur, elle est
ignore. Les oprations sont faites dans lordre dappari-
tion des lments de la squence, de debut (inclus) fn
(exclus). la fn, for_each() retourne lobjet fonction
pass en paramtre.
Voici une faon un peu plus complexe que la combinaison
de copy() et ostream_iterator() pour crire le contenu
dune squence sur la sortie standard :
template <class T>
struct Ecrire : public std::unary_function<T, void>
{
Ecrire(std::ostream& un_fux) : fux(un_fux), compteur(0)
{
}
void operator() (T x)
281
{
fux << x << ;
compteur++;
}

std::ostream& fux;
int compteur;
};

int main(int, char**)
{
int tableau[] = { 1, 2, 3, 4, 5, 6, 7 };
const int taille = sizeof(tableau) / sizeof(int);

Ecrire<int> E = std::for_each(tableau,

tableau+taille, Ecrire<int>(std::cout));
std::cout << std::endl << E.compteur

<< objets crits.\n;


}
Initialiser une squence laide
dun gnrateur de valeurs
#include <algorithm>
ForwardIterator generate(ForwardIterator debut,

ForwardIterator fn, Generator g);


OutputIterator generate_n(OutputIterator debut,

Size n, Generator g);


generate() et generate_n() affectent chaque lment de
la squence [debut, fn[ (respectivement [debut, debut + n[)
le rsultat de la fonction gnratrice g(), puis retourne
litrateur fn (respectivement debut + n).
InIa|scr unc scqucncc a |adc dun gcncraIcur dc va|curs
282 LhAPIJL 12 A|gorIhmcs sIandard
Info
La fonction gnratrice est bien appele n fois. Son rsultat
nest pas stock puis affect tous les lments. Cela peut
paratre lourd si cette fonction retourne le rsultat dun algo-
rithme complexe, mais cela offre la souplesse dutiliser comme
fonction gnratrice une fonction qui ne retourne pas toujours
le mme rsultat, telle une fonction alatoire ou une fonction
incrmentale.
Info
Pour affecter la mme valeur tous les lments de la squence,
utilisez plutt fll() ou fll_n().
Cet exemple crit une liste de valeurs alatoires sur la
sortie standard :
std::generate_n(std::ostream_iterator<int>(std::

cout,\n), 10, rand);


Tester si tous les lments dune
squence sont dans une autre
#include <algorithm>
bool includes(InputIterator debut1, InputIterator

fn1, InputIterator debut2, InputIterator fn2);


bool includes(InputIterator debut1, InputIterator

fn1, InputIterator debut2, InputIterator fn2,

StrictWeakOrdering comp);
includes() teste si tous les lments de la deuxime squence
[debut2, fn2[ sont dans la premire squence [debut1, fn1[.
288
Cette fonction, qui sexcute en temps linaire, requiert que
les deux squences soient tries selon la relation dordre
mentionne (< par dfaut).
#include <iostream>
#include <algorithm>
using namespace std;

#defne TAILLE_TABLEAU(tab) (sizeof(tab) / sizeof(int))

#defne TEST_INCLUDES(tab1,tab2) \
(includes(tab1, tab1 + TAILLE_TABLEAU(tab1), \
tab2, tab2 + TAILLE_TABLEAU(tab2)) \
? oui : non)

#defne PRINT_TABLEAU(tab) \
cout << { << tab[0]; \
for(int i=1; i<TAILLE_TABLEAU(tab); i++) \
cout << , << tab[i]; \
cout << };

#defne PRINT_TEST(tab1,tab2) \
PRINT_TABLEAU(tab1) \
cout << contient ; \
PRINT_TABLEAU(tab2) \
cout << ? << TEST_INCLUDES(tab1,tab2) << endl ;

int A1[] = { 1, 2, 3, 4, 5, 6, 7 };
int A2[] = { 1, 4, 7 };
int A3[] = { 2, 7, 9 };
int A4[] = { 1, 1, 2, 3, 5, 8, 13, 21 };
int A5[] = { 1, 2, 13, 13 };
int A6[] = { 1, 1, 3, 21 };

int main(int,char**)
{
PRINT_TEST(A1,A2)
PRINT_TEST(A1,A3)
PRINT_TEST(A4,A5)
PRINT_TEST(A4,A6)
return 0;
}
JcsIcr s Ious |cs c|cmcnIs dunc scqucncc sonI dans unc auIrc
284 LhAPIJL 12 A|gorIhmcs sIandard
Le programme prcdent produit le rsultat suivant :
{ 1, 2, 3, 4, 5, 6, 7} contient { 1, 4, 7} ? oui
{ 1, 2, 3, 4, 5, 6, 7} contient { 2, 7, 9} ? non
{ 1, 1, 2, 3, 5, 8, 13, 21} contient { 1, 2, 13, 13} ? non
{ 1, 1, 2, 3, 5, 8, 13, 21} contient { 1, 1, 3, 21} ? oui
Calculer le produit intrieur
(produit scalaire gnralis)
de deux squences
#include <algorithm>
T inner_product(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2, T init);


T inner_product(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2, T

init, BinaryFunction1 op1, BinaryFunction2 op2);


La fonction inner_product() calcule le produit intrieur
(un cas particulier bien connu est le produit scalaire) de
deux squences de mme taille. De manire pratique, si la
deuxime squence doit contenir au moins autant dl-
ments que la premire, les autres tant ignors, il vaut
mieux utiliser cette fonction sur des squences de taille
strictement identique.
Le rsultat de la premire version est comparable au
pseudo-code suivant :
T resultat = init;
for (int i=0 ; i<taille(sequence1) ; i++)
resultat = resultat + sequence1[i] * sequence2[i];
La deuxime version utilise lopration resultat =
op1(result, op2(*it1,*it2)).
285
Voici un exemple simple illustrant le produit scalaire de
deux vecteurs :
double V1[3] = { 0.5, 1.2, 5.4 };
double V2[3] = { 10.0, -2.7, 3.76 };
double p = std::inner_product(V1, V1+3, V2, 0.0);
// p == 22.064
Initialiser les lments dune
squence avec une valeur
(en lincrmentant)
#include <numeric>
void iota(ForwardIterator debut,

ForwardIterator fn, T valeur);


iota() affecte un un les lments de la squence [debut, fn[
avec la valeur donne, en lincrmentant entre chaque affec-
tation. Ainsi, le code suivant remplira le tableau dentiers V
avec les valeurs 7, 8, 9, , 16.
std::vector<int> V(10);
std::iota( V.begin(), V.end(), 7);
AIIcnIon
Cette fonction est une extension SGI et ne fait pas partie du
standard. Elle est dcrite ici au cas o vous la rencontreriez dans
du code existant ou si vous travailliez dans cet environnement.
Vous pouvez la trouver dans <ext/numeric> dans lespace de
noms __gnu_cxx avec g++.
InIa|scr |cs c|cmcnIs dunc scqucncc avcc unc va|cur (cn |ncrcmcnIanI)
288 LhAPIJL 12 A|gorIhmcs sIandard
Transformer une squence en tas
et lutiliser
#include <algorithm>
bool is_heap(RandomAccessIterator debut,

RandomAccessIterator fn);
bool is_heap(RandomAccessIterator debut,

RandomAccessIterator fn, StrictWeakOrdering comp);


void make_heap(RandomAccessIterator debut,

RandomAccessIterator fn);
bool make_heap(RandomAccessIterator debut,

RandomAccessIterator fn, StrictWeakOrdering comp);


void sort_heap(RandomAccessIterator debut,

RandomAccessIterator fn);
bool sort_heap(RandomAccessIterator debut, Random

AccessIterator fn, StrictWeakOrdering comp);


void push_heap(RandomAccessIterator debut,

RandomAccessIterator fn);
bool push_heap(RandomAccessIterator debut, Random

AccessIterator fn, StrictWeakOrdering comp);


void pop_heap(RandomAccessIterator debut,

RandomAccessIterator fn);
bool pop_heap(RandomAccessIterator debut, Random

AccessIterator fn, StrictWeakOrdering comp);


is_heap() retourne vrai si la squence [debut, fn[ est un tas,
et faux sinon. La premire version utilise loprateur <, la
seconde la relation dordre comp.
make_heap() transforme lordre des lments de la squence
de manire ce quelle forme un tas.
281
sort_heap() transforme une squence sous forme de tas en
une squence trie standard. Ce tri nest pas un tri stable :
il ne garantit pas la prservation de lordre relatif dl-
ments gaux.
push_heap() ajoute un lment au tas, en postulant que
[debut, fn-1[ est dj un tas et que llment ajouter est
*(fn-1).
pop_heap() supprime les plus grands lments du tas (en
loccurrence *debut). Aprs excution, on retrouve ll-
ment supprim la position fn-1, et les autre lments
sont sous forme de tas dans la squence [debut, fn-1[. Ainsi
un push_heap() suivi dun pop_heap() revient ne rien
faire en y passant du temps.
Info
Un tas est une manire particulire dordonner les lments
dune squence [debut, fn[. Les tas sont utiles, particulirement
pour les tris et les queues de priorit, car ils respectent deux
proprits importantes. Premirement, *debut est le plus grand
lment du tas. Deuximement, il est possible dajouter un lment
un tas (en utilisant push_heap()), ou de supprimer *debut,
en temps logarithmique. En interne, un tas est un arbre stock
sous forme dune squence. Larbre est construit de tel faon que
chaque nud soit plus petit ou gal son nud parent.
std::vector<int> tas(9);
for (int i=0; i<=8; i++) tas[i]=i;

assert(is_heap(tas.begin(),tas.end())==false);
std::copy(tas.begin(),tas.end(),std::ostream_iterator

<int>(std::cout, ));

std::make_heap(tas.begin(), tas.end());
assert(is_heap(tas.begin(),tas.end())==true);
Jransformcr unc scqucncc cn Ias cI |uI|scr
288 LhAPIJL 12 A|gorIhmcs sIandard
std::copy(tas.begin(),tas.end(),std::ostream_iterator

<int>(std::cout, ));

tas.push_back(9);
std::push_heap(tas.begin(),tas.end());
std::copy(tas.begin(),tas.end(),std::ostream_iterator

<int>(std::cout, ));

std::pop_heap(tas.begin(),tas.end());
std::copy(tas.begin(),tas.end(),std::ostream_iterator

<int>(std::cout, ));

std::sort_heap(tas.begin(), tas.end());
assert(is_heap(tas.begin(),tas.end())==false);
std::copy(tas.begin(),tas.end(),std::ostream_iterator

<int>(std::cout, ));
Lexemple prcdent produira la sortie suivante :
0 1 2 3 4 5 6 7 8
8 7 6 3 4 5 2 1 0
9 8 6 3 7 5 2 1 0 4
8 7 6 3 4 5 2 1 0 9
0 1 2 3 4 5 6 7 8 9
Comparer lexicographiquement
deux squences
#include <algorithm>
bool lexicographical_compare(InputIterator1

debut1, InputIterator1 fn1, InputIterator2

debut2, InputIterator2 fn2);


bool lexicographical_compare(InputIterator1

debut1, InputIterator1 fn1, InputIterator2

debut2, InputIterator2 fn2, BinaryPredicate comp);


280
int lexicographical_compare_3way(InputIterator1

debut1, InputIterator1 fn1, InputIterator2

debut2, InputIterator2 fn2);


lexicographical_compare() retourne vrai si la squence
[debut1, fn1[ est lexicographiquement plus petite que la
squence [debut2, fn2[ et faux sinon.
lexicographical_compare_3way() est une gnralisation de
la fonction C strcmp(). Elle retourne un nombre ngatif si
la premire squence est (lexicographiquement) plus petite
que la deuxime, un nombre positif si la deuxime est plus
petite que la premire, et zro sinon (cest--dire si elles
sont lexicographiquement quivalentes).
Info
lexicographical_compare_3way() peut paratre identique
au code suivant :
lexicographical_compare(d1,f1, d2,f2)
? -1
: (lexicographical_compare(d2,f2, d1,f1) ? -1 : 0)
Cest vrai pour le rsultat obtenu, mais faux vis--vis des per-
formances. Un appel lexicographical_compare_3way()
est plus performant que deux appels lexicographical_
compare().
AIIcnIon
Avec g++, lexicographical_compare_3way() se trouve dans
le fchier en-tte <ext/algorithm> et dans lespace de noms
__gnu_cxx.
Lexemple ci-aprs montre que lon peut comparer des
tableaux dentiers comme si lon comparait des chanes de
Lomparcr |cxcographqucmcnI dcux scqucnccs
240 LhAPIJL 12 A|gorIhmcs sIandard
caractres. Il donne un aperu des possibilits quoffrent
ces fonctions.
int A1[] = { 5, 3, 7, 1, 9, 5, 8 };
int A2[] = { 5, 3, 7, 0, 7, 7, 5 };
int A3[] = { 2, 4, 6, 8 };
int A4[] = { 2, 4, 6, 8, 10};

const int N1 = sizeof(A1) / sizeof(int);
const int N2 = sizeof(A2) / sizeof(int);
const int N3 = sizeof(A3) / sizeof(int);
const int N4 = sizeof(A4) / sizeof(int);

int C12 = std::lexicographical_compare(A1, A1+N1, A2,

A2+N2);
int C34 = std::lexicographical_compare(A3, A3+N3, A4,

A4+N4);

int C12w = std::lexicographical_compare(A1, A1+N1, A2,

A2+N2);
int C34w = std::lexicographical_compare(A3, A3+N3, A4,

A4+N4);
int C34b = std::lexicographical_compare(A3, A3+N3, A4,

A4+N4-1);

std::cout << A1 < A2 == << (C12 ? vrai : faux)

<< std::endl;
std::cout << A3 < A4 == << (C34 ? vrai : faux)

<< std::endl;

std::cout << A1 ? A2 == << C12w << std::endl;
std::cout << A3 ? A4 == << C34w << std::endl;
std::cout << A3 ? A4 == << C34b << std::endl;
Cet exemple produira la sortie suivante :
A1 < A2 == faux
A3 < A4 == vrai
A1 ? A2 == 1
A3 ? A4 == -1
A3 ? A4 == 0
241
Chercher le premier/dernier
endroit o insrer une valeur
sans briser lordre dune squence
#include <algorithm>
ForwardIterator lower_bound(ForwardIterator debut,

ForwardIterator fn, const LessThanComparable&

valeur);
ForwardIterator lower_bound(ForwardIterator debut,

ForwardIterator fn, const LessThanComparable&

valeur, StrictWeakOrdering comp);


ForwardIterator upper_bound(ForwardIterator debut,

ForwardIterator fn, const LessThanComparable&

valeur);
ForwardIterator upper_bound(ForwardIterator debut,

ForwardIterator fn, const LessThanComparable&

valeur, StrictWeakOrdering comp);


lower_bound() est une variante de binary_search(). Elle
cherche et renvoie la premire position o la valeur
donne peut tre insre dans la squence trie [debut, fn[
sans rompre le tri.
upper_bound() cherche et renvoie la dernire position pos-
sible.
Dans les deux cas, la squence dentre est suppose trie
selon loprateur < ou la relation dordre comp donne.
Par exemple, le code suivant utilise ces fonctions pour
insrer des valeurs tries selon les dizaines :
#include <iostream>
#include <iterator>
#include <vector>
Lhcrchcr |c prcmcrjdcrncr cndroI ou nscrcr
unc va|cur sans hrscr |ordrc dunc scqucncc
242 LhAPIJL 12 A|gorIhmcs sIandard
#include <ext/algorithm>

struct CompareDizaines
{
bool operator()(int a, int b) const
{
return a/10 < b/10;
}
};

void affche(const std::vector<int>& V)
{
std::cout << V = ;
std::copy(V.begin(), V.end(),

std::ostream_iterator<int>(std::cout, ));
std::cout << (;
if (__gnu_cxx::is_sorted(V.begin(), V.end(),

CompareDizaines()) == false)
std::cout << NON ;
std::cout << tri) << std::endl;
}

int main(int,char**)
{
std::vector<int> V;
std::vector<int>::iterator it;
int valeur;

V.push_back(-123);
V.push_back(- 45);
V.push_back( 0);
V.push_back( 50);
V.push_back( 87);
V.push_back( 83);
V.push_back( 120);
affche(V);

valeur = 82;
it = std::lower_bound(V.begin(), V.end(), valeur,

CompareDizaines());
V.insert(it, valeur);
248
std::cout << \nAprs insertion lower_bound de
<< valeur << :\n;
affche(V);

valeur = 81;
it = std::upper_bound(V.begin(), V.end(), valeur,

CompareDizaines());
V.insert(it, valeur);
std::cout << \nAprs insertion upper_bound de
<< valeur << :\n;
affche(V);

return 0;
}
Ce code produit la sortie suivante :
V = -123 -45 0 50 87 83 120 (tri)

Aprs insertion lower_bound de 82:
V = -123 -45 0 50 82 87 83 120 (tri)

Aprs insertion upper_bound de 81:
V = -123 -45 0 50 82 87 83 81 120 (tri)
Fusionner deux squences tries
#include <algorithm>
OutputIterator merge(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator resultat);


OutputIterator merge(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator resultat,

StrictWeakOrdering comp);
Fusonncr dcux scqucnccs Irccs
244 LhAPIJL 12 A|gorIhmcs sIandard
void inplace_merge(BidirectionalIterator debut,

BidirectionalIterator milieu,

BidirectionalIterator fn);
void inplace_merge(BidirectionalIterator debut,

BidirectionalIterator milieu,

BidirectionalIterator fn, StrictWeakOrdering comp);


merge() combine deux squences tries [debut1, fn1[ et
[debut2, fn2[ en une seule squence trie. Les lments des
deux squences dentre sont copis pour former la
squence [resultat, resultat + (fn1 debut1) + (fn2
debut2)[. Les squences dentre ne doivent pas avoir de
partie commune avec la squence rsultat. Notez gale-
ment que la fonction merge() est stable : si i prcde j dans
une des squence dentre, alors la copie de i prcdera la
copie de j dans la squence rsultat.
inplace_merge() effectue le mme genre dopration. Si
[debut, milieu[ et [milieu, fn[ respectent lordre de tri < (ou
comp), alors la fn de inplace_merge(), [debut, fn[ respecte
lordre de tri < (ou comp). Par respecter lordre de tri, on
entend que pour tous itrateurs i et j dune squence, si i
prcde j, alors *j < *i est faux (respectivement comp(*j,*i)
est faux).
AIIcnIon
La complexit de ces deux algorithmes est diffrente.
merge() est linaire sur le nombre total dlments, soit O(N)
o N vaut (fn1 - debut1) + (fn2 - debut2).
inplace_merge() est un algorithme adaptatif : sa complexit
dpend de la mmoire disponible. Si la premire squence est
vide, aucune comparaison nest faite. Dans le pire des cas, lors-
quil ny a pas de mmoire tampon possible, sa complexit est
en O(N log N), o N vaut debut - fn. Dans le meilleur des cas,
lorsque lon peut allouer une mmoire tampon suffsante, il y
a au plus (fn - debut) - 1 comparaisons.
245
Voici deux exemples illustrant ces fonctions :
int A[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8 };
std::inplace_merge(A, A + 5, A + 9);
std::copy(A, A + 9, std::ostream_iterator<int>

(std::cout, ));
// La sortie est 1 2 3 4 5 6 7 8
int B[] = { 1, 3, 5, 7 };
int C[] = { 2, 4, 6, 8, 9 };
std:: merge(B, B + 4, C, C+5, std::ostream_iterator

<int>(std::cout, ));
// La sortie est 1 2 3 4 5 6 7 8 9
Rcuprer le plus petit/grand
lment
#include <algorithm>
const T& min(const T& x, const T& y);
const T& min(const T& x, const T& y,

BinaryPredicate comp);
const T& max(const T& x, const T& y);
const T& max(const T& x, const T& y,

BinaryPredicate comp);
Comme lindique le nom trs explicite de ces fonctions,
min() et max() retournent le minimum ou le maximum
entre deux valeurs x et y donnes en utilisant loprateur <,
ou le prdicat de comparaison comp fourni. Pour illustrer
ces fonctions, lexemple suivant parle de lui-mme :
std::cout << Le maximum entre 1 et 99 est

<< std::max(1, 99) << std::endl;


std::cout << Le minimum entre a et c

<< std::max(a, c) << std::endl;


ccupcrcr |c p|us pcIIjgrand c|cmcnI
248 LhAPIJL 12 A|gorIhmcs sIandard
Info
Cet algorithme est plus puissant quune macro. Il vite en effet
dans certains cas deffectuer des calculs inutiles. Cest le cas
par exemple lorsque vous souhaitez obtenir le maximum entre
le rsultat de deux appels de fonction, comme max(sqrt(3),
log(27)).
Rcuprer le plus petit/grand
lment dune squence
#include <algorithm>
ForwardIterator min_element(ForwardIterator debut,

ForwardIterator fn);
ForwardIterator min_element (ForwardIterator debut,

ForwardIterator fn, BinaryPredicate comp);


ForwardIterator max_element(ForwardIterator debut,

ForwardIterator fn);
ForwardIterator max_element (ForwardIterator debut,

ForwardIterator fn, BinaryPredicate comp);


min_element() retourne le plus petit lment de la squence
[debut, fn[. Plus exactement, il retourne le premier itra-
teur i appartenant la squence donne tel quaucun
autre itrateur de cette squence pointe vers un lment
plus grand que *i. Cette fonction retourne fn uniquement
si la squence donne est une squence vide.
La deuxime version de min_element() diffre de la pre-
mire en ce quelle nutilise pas loprateur < mais le pr-
dicat binaire comp pour comparer les lments. Ainsi
litrateur i retourn vrife la condition comp(*j, *i) ==
false pour tout j (autre que i lui-mme) de la squence.
241
max_element() fait la mme chose mais renvoie le plus
grand lment. Litrateur i retourn vrife le test (*i <
*j) == false ou comp(*i, *j) == false.
int tableau[] = { 5, 6, 2, 8, 5, 8, 0 };
int N = sizeof(tableau) / sizeof(int);
int* i = std::max_element(tableau, tableau+N);
std::cout << Le plus grand est << *i << la

<< i-tableau+1 << -me position.\n;


Cet exemple produit la sortie suivante :
Le plus grand est 8 la 4-me position.
Trouver le premier endroit
o deux squences diffrent
#include <algoritmh>
std::pair<InputIterator1, InputIterator2>

mismatch(InputIterator1 debut1, InputIterator1

fn1, InputIterator2 debut2);


std::pair<InputIterator1, InputIterator2>

mismatch(InputIterator1 debut1, InputIterator1

fn1, InputIterator2 debut2, BinaryPredicate comp);


mismatch() compare les lments de la premire squence
avec ceux de la deuxime, que lon suppose de mme
taille (sinon les lments supplmentaires sont ignors), et
renvoie le premier endroit o les lments diffrent. Les
lments sont compars, soit avec loprateur ==, soit avec
le prdicat de comparaison comp fourni.
Jrouvcr |c prcmcr cndroI ou dcux scqucnccs dffcrcnI
248 LhAPIJL 12 A|gorIhmcs sIandard
int A1[] = { 3, 1, 3, 5, 3, 7, 8 };
int A2[] = { 3, 1, 3, 5, 4, 9, 2 };
int N = sizeof(A1) / sizeof(int);
std::pair<int*, int*> res = std::mismatch(A1, A1+N, A2);
std::cout << La premire diffrence se situe

lindice << res.frst A1 << std::endl

<< Les valeurs sont : << *(res.frst) << et

<< *(res.second) << std::endl;


Gnrer la prochaine plus
petite/grande permutation
lexicographique dune squence
#include <algorithm>
bool next_permutation(BidirectionalIterator debut,

BinirectionalIterator fn);
bool next_permutation(BidirectionalIterator debut,

BinirectionalIterator fn, StrictWeakOrdering comp);


bool prev_permutation(BidirectionalIterator debut,

BinirectionalIterator fn);
bool prev_permutation(BidirectionalIterator debut,

BinirectionalIterator fn, StrictWeakOrdering comp);


next_permutation() transforme la squence [debut, fn[
donne en la prochaine plus grande permutation, lexico-
graphiquement parlant. Il y a un nombre fni de permuta-
tions distinctes de N lments : au plus N! (factoriel N).
Ainsi, si ces permutations sont ordonnes en ordre lexico-
graphique, il y a une dfnition non ambigu de ce que
240
signife la prochaine plus grande permutation. Donc, si
une telle permutation existe, next_permutation() transforme
[debut, fn[ en celle-ci et renvoie vrai, sinon il la transforme
en la plus petite et renvoie faux.
Si une relation dordre stricte comp est fournie, elle est uti-
lise comme comparaison dlment pour dfnition de
lordre lexicographique la place de loprateur <.
prev_permutation() est linverse de next_permutation().
Elle transforme la squence en la prcdente permutation,
selon le mme critre que prcdemment.
template<class BidiIter>
void le_pire_des_tris(BidiIter deb, BidiIter fn)
{
while (std::next_permutation(deb, fn)) { }
}

int main(int, char**)
{
int A[] = { 8, 3, 6, 1, 2, 5, 7, 4 };
int N = sizeof(A) / sizeof(int);
le_pire_des_tris(A, A+N);
std::copy(A, A+N, std::ostream_iterator<int>(std::

cout, ));
return 0;
}
Cet exemple utilise next_permutation() pour implmenter
la pire des manires de faire un tri. La plupart des algorith-
mes de tri sont en O(n log n), et mme le tri bulles est
seulement en O(n). Celui-ci est en O(n!).
0cncrcr |a prochanc p|us pcIIcjgrandc pcrmuIaIon |cxcographquc dunc scqucncc
250 LhAPIJL 12 A|gorIhmcs sIandard
Faire en sorte que le nime
lment soit le mme que
si la squence tait trie
#include <algorithm>
void nth_element(RandomAccesIterator debut,

RandomAccesIterator n_ieme, RandomAccesIterator

fn);
void nth_element(RandomAccesIterator debut,

RandomAccesIterator n_ieme, RandomAccesIterator

fn, StrickWeakOrdering comp);


nth_element() est comparable partial_sort() en ce sens
quelle ordonne une partie des lments de la squence.
Elle arrange la squence donne de telle sorte que le n_ieme
itrateur pointe sur le mme lment que si la squence
avait t trie compltement. De plus, larrangement est
tel quaucun lment de la squence [n_ieme, fn[ soit plus
petit quun des lments de la squence [debut, n_ieme[.
Encore une fois, cette fonction utilise soit loprateur <,
soit la relation dordre stricte comp fournie pour ordonner
les lments de la squence [debut, fn[.
Info
nth_element() diffre de partial_sort() en ce sens quaucune
des sous-squences gauche et droite ne sont tries. Elle garantit
seulement que tous les lments de la partie gauche sont plus
petits que ceux de la partie droite. En ce sens, nth_element()
est plus comparable une partition qu un tri. Elle fait moins
que partial_sort() et est donc galement plus rapide. Pour
cette raison, il vaut mieux utiliser nth_element() plutt que
partial_sort() lorsquelle est suffsante pour vos besoins.
251
int A[] = { 7, 2, 6, 11, 9, 3, 12, 10, 8, 4, 1, 5 };
const int N = sizeof(A) / sizeof(int);
std::nth_element(A, A+6, A+N);
std::copy(A, A+6, std::ostream_iterator<int>( std::

cout, ));
std::cout << / ;
std::copy(A+6, A+N, std::ostream_iterator<int>(

std::cout, ));
// Affchera : 5 2 6 1 4 3 / 7 8 9 10 11 12
Trier les n premiers lments
dune squence
#include <algorithm>
void partial_sort(RandomAccessIterator debut,

RandomAccessIterator milieu, RandomAccesIterator

fn);
void partial_sort(RandomAccessIterator debut,

RandomAccessIterator milieu, RandomAccesIterator

fn, StrictWeakOrdering comp);


partial_sort() rordonne les lments de la squence
[debut, fn[ de telle sorte quils soient partiellement dans
lordre croissant. Il place les milieu-debut plus petits l-
ments, dans lordre croissant, dans la squence [debut,
milieu[. Les fn-milieu lments restants se retrouvent, sans
ordre particulier, dans la squence [milieu, fn[.
Cette fonction utilise la relation dordre partielle comp
fournie, sinon cest loprateur < qui est utilis.
Cet algorithme effectue environ (fn debut) * log(
middle frst) comparaisons.
Jrcr |cs n prcmcrs c|cmcnIs dunc scqucncc
252 LhAPIJL 12 A|gorIhmcs sIandard
Info
partial_sort(debut, fn, fn) produit le mme rsultat que
sort(debut, fn). Notez toutefois que lalgorithme utilis
nest pas le mme : sort() utilise introsort, une variante de
quicksort, alors que partial_sort() utilise un heapsort (tri
par tas). Mme si ces deux types de tris ont une complexit
analogue, en O(N log N), celui de sort() est 2 5 fois plus
rapide que celui de partial_sort(). Ainsi, pour trier la tota-
lit dune squence, prfrez sort() partial_sort().
Voici un petit exemple pour visualiser leffet de cet algo-
rithme :
int A[] = { 7, 2, 6, 13, 9, 3, 14, 11, 8, 4, 1, 5 };
const int N = sizeof(A) / sizeof(int);
std::partial_sort(A, A + 5, A+ N);
std::copy(A, A+N, std::ostream_iterator<int>(std::cout,

));
// Donne : 1 2 3 4 5 13 14 11, 9, 8, 7, 6.
Copier les n plus petits lments
dune squence
#include <algorithm>
RandomAccessIterator partial_sort_copy

(RandomAccessIterator debut, RandomAccesIterator fn,

RandomAccessIterator debut_resultat,

RandomAccesIterator fn_resultat);
RandomAccessIterator partial_sort_copy

(RandomAccessIterator debut, RandomAccesIterator

fn, RandomAccessIterator debut_resultat,

RandomAccesIterator fn_resultat,

StrictWeakOrdering comp);
258
partial_sort_copy() copie les N plus petits lments de la
squence [debut, fn[ dans la squence [debut_resultat, fn_
resultat[, o N est la taille de la plus petite des deux
squences donnes. Les lments de la squence rsultat
sont bien sr ordonns, suivant la relation dordre comp
fournie ou < le cas chant. Cette fonction retourne
ensuite litrateur debut_resultat + N.
int A[] = { 7, 2, 6, 11, 9, 3, 12, 10, 8, 4, 1, 5 };
const int N = sizeof(A) / sizeof(int);
std::vector<int> V(4);
std::partial_sort_copy(A, A+N, V.begin(), V.end());
std::copy(V.begin(), V.end(), std::ostream_iterator

<int>(std::cout, ));
Lexemple prcdent produit le rsultat suivant :
1 2 3 4
Calculer une somme partielle
gnralise dune squence
#include <numeric>
OutputIterator partial_sum(InputIterator debut,

InputIterator fn, OutputIterator res);


OutputIterator partial_sum(InputIterator debut,

InputIterator fn, OutputIterator res,

BinaryOperation op);
La|cu|cr unc sommc parIc||c gcncra|scc dunc scqucncc
254 LhAPIJL 12 A|gorIhmcs sIandard
partial_sum() calcule une somme partielle gnralise. Pour
faire simple, cest un peu lquivalent du code suivant :
res[0] = debut[0];
for (int i=1 ; i < fn-debut ; i++)
{
res[i] = res[i-1] + debut[i];
// ou res[i] = op(res[i-1], debut[i]);
}
Cette fonction retourne litrateur res+(fn-debut).
Info
res peut avoir la mme valeur que debut. Cela peut tre utile
lorsque vous voulez stocker le rsultat directement dans la
squence dorigine.
De plus, tant donn que lordre des oprations est totalement
dfni, il nest pas ncessaire que loprateur op que vous four-
nissez soit associatif ou commutatif.
Couper la squence en deux
en fonction dun prdicat
#include <algorithm>
ForwardIterator partition(ForwardIterator debut,

ForwardIterator fn, Predicate pred);


ForwardIterator stable_partition(ForwardIterator

debut, ForwardIterator fn, Predicate pred);


partition() rordonne les lments de la squence [debut, fn[
de telle sorte quil existe un itrateur milieu appartenant
255
la squence tel que : les lments de la sous-squence
[debut, milieu[ vrifent pred(*i)==true, et ceux de la sous-
squence [milieu, fn[ vrifent pred(*i)==false. La fonc-
tion retourne cet itrateur milieu.
stable_partition() diffre de partition() en ce sens
quelle prserve lordre relatif des lments. Ainsi, si x et y
sont des lments tels que pred(x) == pred(y) et que x
prcde y, alors x prcdera toujours y aprs lexcution
de stable_sort().
AsIucc
Les fonctions stables sont toujours plus lentes que les fonc-
tions dont la stabilit (au sens de la prservation de lordre des
lments et non de la prsence de bogues, bien sr) nest pas
garantie. Ne les utilisez donc que si cette proprit de stabilit
vous est ncessaire.
Lexemple ci-aprs montre comment sparer les nombres
pairs et les nombres impairs dune squence. Les nombres
pairs sont ici placs au dbut de la squence.
std::vector<int> A(10);
for (int i=0 ; i<10 ; i++) A[i] = i+1;
std::partition(A.begin(), A.end(),

std::compose1(std::bind2nd( std::equal_to<int>(), 0),


std::bind2nd( std::modulus<int>(), 2)));


// La squence contient alors les valeurs :
// 10 2 8 4 6 5 7 3 9 1.
Loupcr |a scqucncc cn dcux cn foncIon dun prcdcaI
258 LhAPIJL 12 A|gorIhmcs sIandard
Calculer x
i
(fonction puissance
gnralise)
#include <numeric>
T power(T x, Integer n);
T power(T x, Integer n, MonoidOperation op);
power() est une gnralisation de la fonction puissance x
n
,
o n est un entier positif.
La premire version retourne x *x *x * x, o x est rpt
n fois. Si n == 0, alors elle retourne std::identity( std::
multiplies<T>() ).
La deuxime version est identique lexception quelle
utilise la fonction op au lieu de multiplies<T> et retourne
std::identity(op) si n == 0.
AIIcnIon
power() ne repose pas sur le fait que la multiplication est
commutative, mais quelle est associative. Si vous dfnissez un
oprateur * ou une opration op qui nest pas associatif, alors
power() donnera une mauvaise rponse.
Info
Une monoid operation est une fonction binaire particulire. Une
fonction binaire doit satisfaire trois conditions pour tre une
opration monode. Premirement, le type de ses deux arguments
et de sa valeur de retour doivent tre les mmes. Deuximement,
il doit exister un lment identit. Troisimement, lopration
doit tre associative. Par exemple, laddition et la multiplication
sont des oprations monodes.
Lassociativit implique que f(x, f(y,z)) == f(f(x,y), z).
Llment identit id respecte les conditions f(x, id) == x et
f(id, x) == x.
251
Info
power() fait partie des extensions SGI et peut tre code dans un
autre espace de noms que std, si elle est prsente dans limpl-
mentation de votre compilateur.
Copier alatoirement un
chantillon dune squence
#include <algorithm>
RandomAccessIterator random_sample(InputIterator

debut,InputIterator fn, RandomAccessIterator

rDebut, RandomAccesIterator rFin);


RandomAccessIterator random_sample(InputIterator

debut, InputIterator fn, RandomAccessIterator

rDebut, RandomAccesIterator rFin,

RandomNumberGenerator& rand);
random_sample() copie alatoirement un chantillon de la
squence [debut, fn[ dans la squence [rDebut, rFin[.
Chaque lment de la squence dentre apparatra au
plus une fois dans celle de sortie. Les lments sont tirs
selon une loi de probabilit uniforme. Lordre relatif des
lments de la squence dentre nest pas prserv (si
vous en avez besoin, jetez un il sur random_sample_n()).
Le nombre n dlments copis est le minimum entre fn
- debut et rFin - rDebut. Du coup, la fonction renvoie
litrateur rDebut + n.
AIIcnIon
Si vous spcifez un gnrateur de nombres alatoires en
paramtre, celui-ci doit produire une distribution uniforme.
Cest--dire que la frquence dapparition de chaque valeur
doit tre la mme.
Lopcr a|caIorcmcnI un cchanI||on dunc scqucncc
258 LhAPIJL 12 A|gorIhmcs sIandard
const int N = 10;
const int n = 4;
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int B[n];

std::random_sample(A, A+N, B, B+n);
std::copy(B, B+n, std::ostream_iterator<int>(std::cout,

));
Le code prcdent affche une des 5 039 possibilits exis-
tantes, comme celle-ci :
7 1 5 2
Copier alatoirement un sous-
chantillon (de n lments), en
prservant leur ordre dorigine
#include <algorithm>
OutpuIterator random_sample_n(ForwardIterator debut,

ForwardIterator fn, OutpuIterator res, Distance n);


OutpuIterator random_sample_n(ForwardIterator debut,

ForwardIterator fn, OutpuIterator res, Distance n,

RandomNumberGenerator& rand);
random_sample_n() copie alatoirement un sous-chan-
tillon (de n lments sil y en a assez) de la squence [debut,
fn[ dans la squence [res, res+n[. Chaque lment de la
squence dentre apparatra au plus une fois dans celle de
sortie. Les lments sont tirs selon une loi de probabilit
uniforme. Lordre relatif des lments de la squence den-
tre est prserv (si vous ne le voulez pas, jetez un il sur
random_sample()).
250
En ralit, le nombre m dlments copis est le minimum
entre fn - debut et n. Du coup, la fonction renvoie litra-
teur res + m.
Comme avec random_sample(), vous pouvez fournir votre
propre gnrateur de nombres alatoires.
const int N = 10;
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

std::random_sample_n(A, A+N, std::ostream_iterator

<int>(std::cout, ), 4);
Le code prcdent affche une des 209 possibilits existan-
tes, comme celle-ci :
1 2 5 7
Mlanger les lments
dune squence
#include <algorithm>
void random_shuffe(RandomAccesIterator debut,

RandomAccesIterator fn);
void random_shuffe(RandomAccesIterator debut,

RandomAccesIterator fn, RandomNumberGenerator&

rand);
random_shuffe() mlange alatoirement les lments de la
squence [debut, fn[. Cette squence se retrouve alors dans
un des N! 1 ragencements possibles, o N est la taille
de la squence. Une fois encore, vous avez la possibilit
dutiliser votre propre gnrateur de nombres alatoires.
Mc|angcr |cs c|cmcnIs dunc scqucncc
280 LhAPIJL 12 A|gorIhmcs sIandard
const int N = 10;
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

std::random_shuffe(A, A+N);
std::copy(A, A+N, std::ostream_iterator<int>

(std::cout, ));
Le code prcdent affche une des 3 628 899 (soit 10! 1)
autres possibilits existantes, comme celle-ci :
9 8 3 1 6 5 2 4 10 7
Supprimer certains lments
dune squence
#include <algorithm>
ForwardIterator remove(ForwardIterator deb,

ForwardIterator fn, const T& valeur);


ForwardIterator remove_if(ForwardIterator deb,

ForwardIterator fn, Predicate test);


remove() supprime de la squence [debut, fn[ tous les l-
ments gaux la valeur donne, puis retourne le nouvel
itrateur de fn. Cette fonction est stable : elle prserve
lordre relatif des lments conservs.
remove_if() fait de mme en supprimant les lments
vrifant le test donn.
281
AIIcnIon
Le sens du mot supprimer est quelque peu dform dans
le contexte de ces fonctions. remove() et remove_if() ne
dtruisent aucun itrateur. Ainsi la distance entre deb et fn
restera inchange. Par exemple, si la squence V donne est un
vecteur (std::vector<>), alors V.size() retournera la mme
taille avant et aprs la suppression.
Litrateur renvoy indique donc que les lments qui le suivent
sont sans intrt, et les valeurs des lments sur lesquels ils
pointent ne sont pas garanties.
Si vous voulez rellement supprimer les lments dune squen-
ce S, vous pouvez utiliser une formule de ce type : S.erase
(std::remove(S.begin, S.end(), x), S.end()).
std::vector<int>::iterator fn2;
std::vector<int> V;
V.push_back(3);
V.push_back(5);
V.push_back(2);
V.push_back(3);
V.push_back(8);
V.push_back(7);
fn2 = std::remove(V.begin(), V.end(), 3);
std::copy(V.begin(), fn2, std::ostream_iterator

<int>

(std::cout, ));
// Affche : 5 2 8 7
Supprmcr ccrIans c|cmcnIs dunc scqucncc
282 LhAPIJL 12 A|gorIhmcs sIandard
Copier une squence en
omettant certains lments
#include <algorithm>
OutputIterator remove_copy(ForwardIterator deb,

ForwardIterator fn, OutputIterator res, const T&

valeur);
OutputIterator remove_copy_if(ForwardIterator deb,

ForwardIterator fn, OutputIterator res, Predicate

test);
remove_copy() copie tous les lments non gaux la
valeur donne de la squence [debut, fn[ dans la squence
commenant litrateur res. Cette fonction est stable :
elle prserve lordre relatif des lments conservs.
remove_copy_if() fait de mme en copiant les lments ne
vrifant pas le test donn.
AIIcnIon
La squence rsultat doit tre assez grande pour contenir
lensemble des lments qui y seront copis. Nhsitez pas
faire usage des std::back_insert_iterator, std::front_
insert_iterator ou autre utilitaire dans ce contexte.
std::vector<int> V;
V.push_back(3);
V.push_back(5);
V.push_back(2);
V.push_back(3);
V.push_back(8);
V.push_back(7);
std::remove_copy_if(V.begin(), V.end(),

std::ostream_iterator<int>(std::cout, ),

std::bind2nd(std::less_equal<int>(),3) );
// Affche : 5 8 7
288
Remplacer certains lments
dune squence
#include <algorithm>
void replace(ForwardIterator deb, ForwardIterator fn,

const T& ancienne_valeur, const T& nouvelle_valeur);


void replace_if(ForwardIterator deb, ForwardIterator

fn, Predicate test, const T& nouvelle_valeur);


OutputIterator replace_copy(InputIterator deb,

InputIterator fn, OutputIterator res, const T&

ancienne_valeur, const T& nouvelle_valeur);


OutputIterator replace_copy_if(InputIterator deb,

InputIterator fn, OutputIterator res, Predicate

test, const T& nouvelle_valeur);


replace() remplace tous les lments de [deb, fn[ gaux
lancienne_valeur par la nouvelle_valeur. Ainsi tous les
itrateurs i tels que *i == ancienne_valeur alors *i = nou-
velle_valeur.
replace_if() remplace les lments vrifant le prdicat
test(*i) == true.
replace_copy() et replace_copy_if() procde de mme
mais effectue les remplacements sur (et pendant) la copie.
std::vector<int> V;
V.push_back(3);
V.push_back(5);
V.push_back(2);
V.push_back(3);
V.push_back(8);
V.push_back(7);
std::list<int> V2;
std::replace_copy_if(V.begin(), V.end(),

std::front_insert_iterator< std::list<int> >(V2),


std::bind2nd(std::less_equal<int>(),3), 0 );
cmp|accr ccrIans c|cmcnIs dunc scqucncc
284 LhAPIJL 12 A|gorIhmcs sIandard
std::copy(V2.begin(), V2.end(),

std::ostream_iterator<int>(std::cout, ));
// Affche : 7 8 0 2 5 0
Inverser lordre de la squence
#include <algorithm>
void reverse(BidirectionalIterator deb,

BidirectionalIterator fn);
OutputIterator reverse_copy(BidirectionalIterator

deb, BidirectionalIterator fn, OutputIterator res);


reverse() inverse lordre des lments de la squence.
reverse_copy() copie la squence en inversant lordre lors
de la copie.
Si A est un vecteur contenant les lments 1, 2, 3, 4, 5, alors
le code suivant inverse lordre de ses lments de sorte
quil contienne 5, 4, 3, 2, 1.
std::reverse(A.begin(), A.end());
Effectuer une rotation des
lments de la squence
#include <algorithm>
ForwardIterator rotate(ForwardIterator debut,

ForwardIterator milieu, ForwardIterator fn);


OutputIterator rotate_copy(ForwardIterator debut,

ForwardIterator milieu, ForwardIterator fn,

OutputIterator res);
285
rotate() effectue une rotation des lments de la squence.
Ainsi, llment la position milieu est dplac la posi-
tion debut, llment la position milieu + 1 est dplac
la position debut + 1, et ainsi de suite. Une autre manire de
voir les choses est de dire que cette fonction change les
deux sous-squences [debut, milieu[ et [milieu, fn[. Enfn,
cette fonction retourne lquivalent de debut + (fn milieu),
la nouvelle position du premier lment de la squence
dentre.
Info
Certaines implmentations de rotate() retournent void.
rotate_copy() copie le rsultat dans la squence commen-
ant la position res plutt que dcraser la squence
dorigine, puis retourne result + (last - frst).
char alphabet[] = abcdefghijklmnopqrstuvwxyz;
std::rotate(alphabet, alphabet + 5, alphabet + 26);
std::cout << alphabet << std::endl;
// Affchera : fghijklmnopqrstuvwxyzabcde
Chercher une sous-squence
#include <algorithm>
ForwardIterator1 search(ForwardIterator1 debut1,

ForwardIterator1 fn1, ForwardIterator2 debut2,

ForwardIterator2 fn2);
ForwardIterator1 search(ForwardIterator1 debut1,

ForwardIterator1 fn1, ForwardIterator2 debut2,

ForwardIterator2 fn2, BinaryPredicate comp);


Lhcrchcr unc sous-scqucncc
288 LhAPIJL 12 A|gorIhmcs sIandard
ForwardIterator search_n(ForwardIterator debut,

ForwardIterator fn, Size n, const T& valeur);


ForwardIterator search_n(ForwardIterator debut,

ForwardIterator fn, Size n, const T& valeur,

BinaryPredicate comp);
ForwardIterator1 fnd_end(ForwardIterator1 debut1,

ForwardIterator1 fn1, ForwardIterator2 debut2,

ForwardIterator2 fn2);
ForwardIterator1 fnd_end(ForwardIterator1 debut1,

ForwardIterator1 fn1, ForwardIterator2 debut2,

ForwardIterator2 fn2, BinaryPredicate comp);


La fonction search() cherche la premire sous-squence
identique [debut2, fn2[ apparaissant dans [debut1, fn1[.
La fonction search_n() cherche la premire sous-squence
de n occurrences conscutives de valeur dans [debut1, fn1[.
La fonction fnd_end() porte mal son nom et aurait d
sappeler search_end() car son comportement est plus
proche de search() que de fnd(). Comme search(), elle
cherche une sous-squence de [debut1, fn1[ qui soit iden-
tique [debut2, fn2[. La diffrence tient au fait que search()
cherche la premire occurrence, alors que fnd_end() cherche
la dernire. Si elle existe, fnd_end() retourne un itrateur
sur le dbut de la sous-squence trouve ; sinon, elle
retourne fn1.
La premire version de fnd_end() utilise loprateur ==. La
deuxime le prdicat comp donn en testant si comp( *(i +
(j-debut2)), *j) est vrai pour un i donn de la premire
squence et pour tout j de la squence cherche. Le mme
principe est valable pour search() et search_n().
281
Le programme suivant illustre lutilisation de ces diffren-
tes fonctions :
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

bool ci_equal(char ch1, char ch2)
{
return toupper((unsigned char)ch1)

== toupper((unsigned char)ch2);
}

int main(int, char**)
{
string s = Exeexecutable.exe;
string t = exe;

string::iterator i;
i = fnd_end(s.begin(), s.end(), t.begin(), t.end());

if (i != s.end())
{
cout << fnd_end => Trouv position ;
cout << (i-s.begin()) << : ;
copy(i,i+t.size(),ostream_iterator<char>(cout));
cout << << endl;
}

i = search(s.begin(), s.end(), t.begin(), t.end());
if (i != s.end())
{
cout << search => Trouv position ;
cout << (i-s.begin()) << : ;
copy(i,i+t.size(),ostream_iterator<char>(cout));
cout << << endl;
}

i = search(s.begin(), s.end(), t.begin(), t.end(),

ci_equal);
if (i != s.end())
Lhcrchcr unc sous-scqucncc
288 LhAPIJL 12 A|gorIhmcs sIandard
{
cout << search+pred => Trouv position ;
cout << (i-s.begin()) << : ;
copy(i,i+t.size(),ostream_iterator<char>(cout));
cout << << endl;
}

i = search_n(s.begin(), s.end(), 2, e, ci_equal);
if (i != s.end())
{
cout << search_n => Trouv position ;
cout << (i-s.begin()) << : ;
copy(i,i+2,ostream_iterator<char>(cout));
cout << << endl;
}

return 0;
}
Il produit la sortie suivante :
fnd_end => Trouv position 14 : exe
search => Trouv position 3 : exe
search+pred => Trouv position 0 : Exe
search_n => Trouv position 2 : ee
Construire la diffrence de deux
squences tries
#include <algorithm>
OutputIterator set_difference(InputIterator1 debut1,

InputIterator1 fnt1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res);


OutputIterator set_difference(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res,

StrictWeakOrdering comp);
280
set_difference() construit la diffrence des deux squen-
ces tries [debut1, fn1[ et [debut2, fn2[. Le rsultat est une
squence trie commenant litrateur res donn et
fnissant litrateur retourn par la fonction.
Dune manire simple, cette diffrence correspond celle
de la thorie des ensembles. Le rsultat est lensemble des
lments de [debut1, fn1[ qui ne sont pas dans [debut2, fn2[.
La ralit est un peu plus complexe : des lments peuvent
apparatre plusieurs fois dans chacune des squences. Dans
ce cas, si un lment apparat m fois dans la premire squence
et n fois dans la deuxime, alors il sera max(m-n, 0) fois dans
la squence rsultat.
Info
Cette fonction est stable car elle prserve aussi lordre dappa-
rition des lments considrs comme identiques.
La deuxime version de set_difference() utilise la rela-
tion dordre donne au lieu de loprateur <.
inline bool lt_nocase(char c1, char c2)
{
return std::tolower(c1) < std::tolower(c2);
}

int main()
{
int A1[] = {1, 3, 5, 7, 9, 11};
int A2[] = {1, 1, 2, 3, 5, 8, 13};
char A3[] = {a, b, b, B, B, f, g, h,

H};
char A4[] = {A, B, B, C, D, F, F, H };

const int N1 = sizeof(A1) / sizeof(int);
LonsIrurc |a dffcrcncc dc dcux scqucnccs Irccs
210 LhAPIJL 12 A|gorIhmcs sIandard
const int N2 = sizeof(A2) / sizeof(int);
const int N3 = sizeof(A3);
const int N4 = sizeof(A4);

std::cout << Difference A1 - A2 : ;
std::set_difference(A1, A1 + N1, A2, A2 + N2,

std::ostream_iterator<int>(std::cout, ));
std::cout << std::endl << Difference A3 - A4 : ;
std::set_difference(A3, A3 + N3, A4, A4 + N4,

std::ostream_iterator<char>(std::cout, ),

lt_nocase);
std::cout << std::endl;
}
Cet exemple produira la sortie ci-aprs. Notez bien la
manire dont elle conserve les lments : ce sont les premi
res occurrences identiques qui sont supprimes.
Difference A1 - A2 : 7 9 11
Difference A3 - A4 : B B g H
Construire lintersection
de deux squences tries
#include <algorithm>
OutputIterator set_intersection(InputIterator1 debut1,

InputIterator1 fnt1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res);


OutputIterator set_intersection(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res,

StrictWeakOrdering comp);
211
set_intersection() construit lintersection des deux
squence tries [debut1, fn1[ et [debut2, fn2[. Le rsultat est
une squence trie commenant litrateur res donn et
fnissant litrateur retourn par la fonction.
Cette intersection correspond celle de la thorie des
ensembles. Le rsultat est lensemble des lments qui sont
la fois des lments de [debut1, fn1[ et de [debut2, fn2[. La
ralit est un peu plus complexe : des lments peuvent
apparatre plusieurs fois dans chacune des squences. Dans
ce cas, si un lment apparat m fois dans la premire
squence et n fois dans la deuxime, alors il sera min(m,-n)
fois dans la squence rsultat.
Info
Cette fonction est stable car elle prserve aussi lordre dappa-
rition des lments considrs comme identiques.
La deuxime version de set_intersection() utilise la rela-
tion dordre donne au lieu de loprateur <.
En reprenant les valeurs de lexemple de set_difference()
mais en appliquant set_intersection(), on obtient le rsul-
tat suivant :
Intersection de A1 et A2 : 1 3 5
Intersection de A3 et A4 : a b b f h
Vous remarquerez que ce sont les premires apparitions de la
premire squence qui sont conserves.
LonsIrurc |nIcrsccIon dc dcux scqucnccs Irccs
212 LhAPIJL 12 A|gorIhmcs sIandard
Construire la diffrence symtrique
des deux squences tries
#include <algorithm>
OutputIterator set_symmetric_difference(InputIterator1

debut1, InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res);


OutputIterator set_symmetric_difference(InputIterator1

debut1, InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res,

StrictWeakOrdering comp);
set_symmetric_difference() construit la diffrence sym-
trique des deux squences tries [debut1, fn1[ et [debut2,
fn2[. Cette nouvelle squence est aussi trie selon lopra-
teur < ou comp fourni. Litrateur retourn est la fn de
cette squence rsultat.
L encore, dans le cas simple, set_symmetric_difference()
effectue un calcul de la thorie des ensembles : elle construit
lunion des deux ensembles A B et B A, o A et B sont les
deux squences dentre. La squence rsultat R contient
une copie des lments de A qui ne sont pas dans B, et une
copie des lments de B qui ne sont pas dans A.
Lorsque A et/ou B contiennent des lments semblables, la
rgle suivante est applique : si un lment apparat m fois
dans A et n fois dans B, alors il apparat
|
m n
|
fois dans R.
Cette fonction est stable et prserve lordre dapparition
des lments semblables qui se suivent.
En reprenant encore les valeurs de lexemple de set_dif-
ference() mais en appliquant cette fois-ci set_symmetric_
difference(), on obtient le rsultat suivant :
218
Intersection symtrique de A1 et A2 : 1 2 7 8 9 11 13
Intersection symtrique de A3 et A4 : B B C D F g H
Si m > n, alors les m n derniers lments de A sont conser-
vs. Si n < m, alors les n m derniers lments de B sont
conservs.
Construire lunion de deux
squences tries
#include <algorithm>
OutputIterator set_union(InputIterator1

debut1, InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res);


OutputIterator set_union(InputIterator1

debut1, InputIterator1 fn1, InputIterator2 debut2,

InputIterator2 fn2, OutputIterator res,

StrictWeakOrdering comp);
set_union() construit la squence trie rsultant de lunion
des deux squences tries fournies. Le tri correspond soit
loprateur <, soit la relation dordre partielle stricte
comp fournie.
Dans le cas simple, cette fonction correspond lunion de
la thorie des ensembles. Le rsultat contient une copie de
chaque lment apparaissant dans lun, lautre ou les deux
squences donnes.
Le cas gnral repose sur cette rgle : si un lment appa-
rat m fois dans [debut1, fn1[ et n fois dans [debut2, fn2[,
alors il apparatra max(m, n) fois dans le rsultat.
Une fois encore, cette fonction est stable et prserve lordre
relatif des lments semblables.
LonsIrurc |unon dc dcux scqucnccs Irccs
214 LhAPIJL 12 A|gorIhmcs sIandard
Un set_union() sur les valeurs des exemples prcdents
(que lon retrouve dans lexemple de set_difference())
produira le rsultat suivant :
Union de A1 et A2 : 1 1 2 3 5 7 8 9 11 13
Union de A3 et A4 : a b B B C D f F H h
Si un lment apparat m fois dans [debut1, fn1[ et n fois
dans [debut2, fn2[, alors les m lments de [debut1, fn1[ puis
les max(n-m, 0) premiers de [debut2, fn2[ seront copis dans
le rsultat. Notez que cette information nest utile que si
vous nutilisez pas une relation dordre totale mais par-
tielle ; cas dans lesquels des lments peuvent tre quiva-
lents (ou semblables) pas mais gaux, afn de bien
comprendre quels lments sont conservs.
Trier une squence
#include <algorithm>
bool is_sorted(ForwardIterator debut, ForwardIterator

fn);
bool is_sorted(ForwardIterator debut, ForwardIterator

fn, StreakWeakOrdering comp);


bool sort(ForwardIterator debut, ForwardIterator fn);
bool sort(ForwardIterator debut, ForwardIterator fn,

StreakWeakOrdering comp);
is_sorted() teste si la squence est trie ou non selon la
relation dordre comp (ou <). Pour cela, elle teste si deux
lments conscutifs a et b sont tels que comp(b,a) (ou b<a)
est faux.
215
sort() trie la squence selon la relation dordre donne.
stable_sort() trie galement la squence selon la relation
dordre donne, mais prserve lordre dorigine des l-
ments de valeurs quivalentes : cest un tri stable. Utilisez-
le uniquement si cette caractristique vous est ncessaire
(le tri stable est plus lent que le tri simple).
int A[] = { 1, 4, 7, 2, 5, 7, 9 };
const int N = sizeof(A) / sizeof(int);
assert( is_sorted(A,A+N) == false );
std::sort(A, A+N);
assert( is_sorted(A,A+N) == true );
AIIcnIon
Avec g++, is_sorted() se trouve dans <ext/algorithm> dans
lespace de noms __gnu_cxx.
changer le contenu de
deux variables, itrateurs
ou squences
#include <algorithm>
void swap(Assignable& a, Assignable& b);
void iter_swap(ForwardIterator1 a, ForwardIterator2 b);
void swap_ranges(ForwardIterator1 debut1,

ForwardIterator1 fn1, ForwardIterator2 debut2,

ForwardIterator2 fn2);
swap() change le contenu de deux variables.
iter_swap() est quivalent swap(*a, *b). Strictement par-
lant, cette fonction est redondante et serait donc inutile.
Lchangcr |c conIcnu dc dcux varah|cs, IcraIcurs ou scqucnccs
218 LhAPIJL 12 A|gorIhmcs sIandard
Sa prsence est due une raison technique : certains com-
pilateurs ont parfois du mal dduire le type requis pour
appeler la bonne instanciation de swap(*a, *b).
swap_range() change le contenu de deux squences de
mme taille. Les deux squences ne doivent pas avoir de
partie commune.
std::vector<int> A,B;
A.push_back(1);
A.push_back(2); // A = { 1, 2 }
B.push_back(3);
B.push_back(4); // B = { 3, 4 }

std::swap(A[0],A[1]);
// A = { 2, 1 } et B = { 3, 4 }
std::iter_swap(A.begin(), B.begin());
// A = { 3, 1 } et B = { 2, 4 }
std::swap_ranges(A.begin(), A.end(), B.begin(), B.end());
// A = { 2, 4 } et B = { 3, 1 }
Transformer une (ou deux)
squences en une autre
#include <algorithm>
OutputIterator transform(InputIterator debut,

InputIterator fn, OutputIterator res,

UnaryFunction op);
OutputIterator transform(InputIterator1 debut1,

InputIterator1 fn1, InputIterator2 debut2,

OutputIterator res, BinaryFunction op_binaire);


Par dfnition, transform() effectue une opration sur des
objets. La premire version utilise une squence, la
deuxime en utilise deux.
211
Dans le premier cas, transform() applique le foncteur
chaque objet et laffecte litrateur de sortie : *o = op(*i)
puis incrmente celui-ci. Enfn elle retourne litrateur
correspondant la fn de la squence de sortie.
Dans le deuxime cas, transform() affecte litrateur de
sortie le rsultat de op_binaire(*i1,*i2), en faisant pro-
gresser simultanment (paralllement) i1 et i2 sur chacune
des deux squences fournies.
AIIcnIon
On est vite tent dutiliser for_each la place de transform
pour transformer une squence. Cela savre tout fait possi-
ble dans la pratique mais doit absolument tre vit, car cela
romprait la smantique de for_each() qui est quelle ne
modife jamais une squence.
Dans ce cas, utiliser transform() en utilisant le mme itra-
teur pour debut et res. Il serait dailleurs agrable que soit
ajoute la STL cette fn une fonction transform() ne pre-
nant pas ditrateur res. Sinon, il est facile de lajouter vous-
mme. Voici une possibilit :
namespace std
{
template <class Conteneur1, class Conteneur2,

class UnaryFunction>

inline void transform_all(Conteneur1 c, Conteneur2 r,

UnaryFunction op)
{
transform(c.begin(), c.end(), r.begin(), op);
}
}

Jransformcr unc (ou dcux) scqucnccs cn unc auIrc
218 LhAPIJL 12 A|gorIhmcs sIandard
Lexemple suivant calcule la somme de deux vecteurs V1
et V2 de mme taille (bien sr).
std::transform(V1.begin(), V1.end(), V2.begin(),

V1plusV2.begin(), std::plus<int>());
Et celui-ci transforme un vecteur de rels en son oppos :
std::transform(V1.begin(), V1.end(),V1.begin(),

std::negate<double>());
AIIcnIon
Litrateur de sortie res ne doit jamais faire partie de la
squence dentre, lexception de debut lui-mme, sous
peine dobtenir des rsultats imprvisibles.
Supprimer les doublons dune
squence (dans ou lors dune copie)
#include <algorithm>
ForwardIterator unique(ForwardIterator debut,

ForwardIterator fn);
ForwardIterator unique(ForwardIterator debut,

ForwardIterator fn, BinaryPredicate predicat);


OutputIterator unique_copy(InputIterator debut,

InputIterator fn, OutputIterator res);


OutputIterator unique_copy(InputIterator debut,

InputIterator fn, OutputIterator res,

BinaryPredicate predicat);
210
Ds quun groupe dlments dupliqus apparat dans la
squence [debut, fn[, la fonction unique() les supprime
tous sauf un. Ainsi, unique() renvoie litrateur nouvelle_fn
tel que la squence [debut, nouvelle_fn[ ne contienne
aucun lment dupliqu, autrement dit aucun doublon.
Les itrateurs de la squence [nouvelle_fn, fn[ sont dj
drfrencs, et les lments sur lesquels ils pointent sont
indtermins. unique() est stable et prserve lordre relatif
des lments conservs.
Une squence [a, b[ est un groupe de doublons si pour
tout itrateur i de cette squence i == a ou *i == *(i-1),
pour la premire version de unique(). Pour la deuxime
version ce sera si i == a ou predicat(*i,*(i-1)) est vrai.
Les deux versions de unique_copy() agissent de mme mais
ne modifent pas la squence dentre et produisent une
nouvelle squence ne contenant aucun doublon. Elles
renvoient litrateur de fn de cette nouvelle squence.
AIIcnIon
Ces fonctions ne suppriment que les doublons conscutifs. Ainsi,
si un vector<int> V contient les valeurs 1, 3, 3, 3, 2, 2, 1,
alors un appel unique() produira un vecteur contenant les
valeurs 1, 3, 2, 1.
Lexemple ci-aprs supprime tous les caractres identiques
en ignorant la casse. Cela est fait en deux tapes : dabord
en triant le contenu alphabtiquement, puis en suppri-
mant les doublons conscutifs.
Supprmcr |cs douh|ons dunc scqucncc (dans ou |ors dunc copc)
280 LhAPIJL 12 A|gorIhmcs sIandard
inline bool eq_insensitif(char c1, char c2)
{
return std::tolower(c1) == std::tolower(c2);
}
inline bool inf_insensitif(char c1, char c2)
{
return std::tolower(c1) < std::tolower(c2);
}
void lettres_utilisees(const char *chaine)
{
std::cout << chaine << std::endl;

std::vector<char> V(chaine, chaine + strlen(chaine));
std::sort(V.begin(), V.end(), inf_insensitif);
std::copy(V.begin(), V.end(), std::ostream_iterator

<char>(std::cout));
std::cout << std::endl;

std::vector<char>::iterator fn2 =

std::unique(V.begin(), V.end(), eq_insensitif);


std::copy(V.begin(), fn2, std::ostream_iterator

<char>(std::cout));
std::cout << std::endl;
}
Lappel de lettres_utilisees(La Bibliotheque Cpp Standard);
produira la sortie ci-aprs.
La Bibliotheque Cpp Standard
aaaBbCddeehiilLnoppqrSttu
aBCdehilnopqrStu
281
Copier laide du constructeur
par copie
#include <memory>
ForwardIterator2 uninitialized_copy(ForwardIterator1

debut, ForwardIterator1 fn, ForwardIterator2 res);


ForwardIterator uninitialized_copy_n(InputIterator

debut, Size N, ForwardIterator res);


En C++, loprateur new alloue de la mmoire pour un
objet et appelle ensuite le constructeur sur ce nouvel empla-
cement mmoire. Occasionnellement, il est utile de pouvoir
sparer ces deux oprations (ce principe est utilis dans
limplmentation de certains conteneurs). Si chaque itra-
teur de la squence [res, res + (fn debut)[ pointe vers
une portion mmoire non initialise, alors uninitialized_
copy() cre une copie de [debut, fn[ dans cette squence.
Ainsi, pour chaque itrateur i de la squence dentre, cette
fonction cre un copie de *i lemplacement mmoire
indiqu par litrateur correspondant dans la squence de
sortie en appelant construct(&*(res + i frst), *i).
uninitialized_copy_n() procde de mme avec [debut,
debut + N[ comme squence copier.
class Entier
{
public:
Entier(int e) : m_entier(e) {}
int get() const { return m_entier; }
private:
int m_entier;
};
Lopcr a |adc du consIrucIcur par copc
282 LhAPIJL 12 A|gorIhmcs sIandard
void test()
{
int valeurs[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const int N = sizeof(valeurs) / sizeof(int);

Entier* entiers = (Entier*) malloc(N *

sizeof(Entier));
std::uninitialized_copy(valeurs, valeurs + N,

entiers);
}
Initialiser laide du
constructeur par copie
#include <memory>
void uninitialized_fll(ForwardIterator debut,

ForwardIterator fn, const T& x);


void uninitialized_fll_n(InputIterator debut,

Size N, const T& x);


En C++, loprateur new alloue de la mmoire pour un
objet et appelle ensuite le constructeur sur ce nouvel
emplacement mmoire. Occasionnellement, il est utile de
pouvoir sparer ces deux oprations (ce principe est utilis
dans limplmentation de certains conteneurs). Si chaque
itrateur de la squence [debut, fn[ pointe vers une por-
tion mmoire non initialise, alors uninitialized_fll()
cre autant de copies de x que ncessaire dans cette
squence. Ainsi, pour chaque itrateur i de la squence
dentre, cette fonction cre une copie de x lemplace-
ment mmoire indiqu par cet itrateur en appelant
construct(&*i, x).
288
uninitialized_fll_n() procde de mme avec [debut, debut
+ N[ comme squence copier.
Lexemple suivant rutilise la classe Entier de lexemple
des fonctions prcdentes :
Entier* test_initialisation(int val, int quantite)
{
Entier valeur(val);
Entier* entiers = (Entier*) malloc(quantite *

sizeof(Entier));
std::uninitialized_fll(entiers, entiers +

quantite, valeur);
return entiers;
}
InIa|scr a |adc du consIrucIcur par copc
13
800SJ
BOOST sinscrit dans le prolongement de la bibliothque
standard STL. BOOST est une sorte de super-biblioth-
que. Il sagit en effet dun ensemble de bibliothques ru-
nies en une seule. BOOST, conu pour tre utilis dans un
vaste spectre dapplications, est largement rpandu. Sa
licence (la BOOST licence) encourage aussi bien un usage
commercial que non commercial.
Dix bibliothques de BOOST sont dj incluses dans le
TR1 (rapport technique du comit de standardisation du
langage C++) et dans les dernires versions de la STL.
Dautres bibliothques de BOOST ont t proposes pour
le prochain TR2. Tout programmeur C++ donc relle-
ment intrt connatre BOOST.
BOOST fonctionne sur tout systme dexploitation
moderne, quil sagisse des systmes Unix, GNU/Linux
ou Windows. Les distributions GNU/Linux et Unix les
plus populaires, comme Fedora, Debian ou NetBSD
incluent des packages pr-compils de BOOST.
Cerise sur le gteau, certaines bibliothques de BOOST
nont mme pas besoin dtre compiles. En effet, BOOST
repose massivement sur les templates
Vous pouvez tlcharger BOOST sur http://www.boost
.org.
288 LhAPIJL 18 800SJ
Mettre en forme des arguments
selon une chane de formatage
boost::format(format-string) % arg1 % arg2 % % argN;
La bibliothque boost::format fournit une classe pour la
mise en forme darguments selon une chane de formatage,
comme le fait printf. Il existe cependant deux diffrences
majeures :
format envoie les arguments dans un fux interne et est
donc compltement scurise et supporte les types uti-
lisateurs de faon transparente ;
les points de suspension () ne peuvent pas tre utiliss
dans un contexte fortement typ ; ainsi lappel de la
fonction avec un nombre arbitraire darguments est
remplac par des appels successifs un fournisseur dargu
ment : loprateur %.
La chane de formatage contient les directives spciales qui
seront remplaces par les chanes rsultant de la mise en
forme des arguments donns.
Notez quen tant que fonction scurise, boost::format
contrle le nombre darguments en fonction de la chane
de formatage. Ainsi, avec la chane de formatage %1% %10%
%3%, il est impratif de fournir dix arguments. En mettre
plus ou moins provoque la leve dune exception.
Une spcifcation de format spec est de la forme : [N$]
[attributs] [ largeur ] [ . prcision ] caractre-de-type
N$ (optionnel). Indique que la spcifcation de format
sapplique au N-ime argument. On ne peut pas mixer
des spcifcations avec ou sans indicateur de position
dargument dans une mme chane de formatage ;
281
Attributs (optionnel). Un formatage du texte peut
tre indiqu grce une suite dattributs choisis parmi
les possibilits dcrites dans le tableau suivant.
Attributs
AIIrhuI SgncaIon LffcI sur |c ux nIcrnc
- Aligner gauche N/A (appliqu plus tard sur la chane)
= Centrer N/A (appliqu plus tard sur la chane)
1
_ Alignement interne Utiliser lalignement interne
1
+ Affcher le signe Utiliser showpos des nombres positifs
# Affcher la base Utiliser showbase et showpoint et la
dcimale
0 Remplir avec des 0
(aprs le signe
ou la base)
Si pas dalignement gauche, appelle
setfll(0) et utilise internal
Des actions supplmentaires sont faites
aprs la conversion de fux pour les
sorties personnalises.
Si la chane ne
commence pas par +
ou , insrer un espace
avant la chane convertie
N/A (appliqu plus tard sur la chane)
Comportement diffrent de printf :
il nest pas affect par lalignement
interne
1. Nouvelle fonctionnalit par rapport printf.
Largeur (optionnel). Indique une largeur minimale
pour la chane rsultant de la conversion. Si ncessaire,
la chane sera complte avec le caractre choisi soit par
le manipulateur de fux, soit par celui mentionn dans la
chane de formatage (par exemple attributs 00, -, ) ;
McIIrc cn formc dcs argumcnIs sc|on unc chanc dc formaIagc
288 LhAPIJL 18 800SJ
Prcision (optionnel). Spcife la prcision du fux
(elle est toujours prcde dun point).
lorsque lon crit un nombre de type rel, il indique
le nombre maximum de chiffres : aprs le point dci-
mal en mode fxe ou scientifque ; au total en mode
par dfaut (%g),
lorsquon lutilise avec un type chane s ou S il sert
limiter la chane convertie aux prcision premiers
caractres (avec un ventuel remplissage jusqu
obtenir largeur caractres aprs cette troncature),
Caractre-de-type. Nimpose pas largument concern
tre de ce type mais dfnit les options associes au
type mentionn (voir le tableau ci-aprs).
Caractres de type
LaracIcrc SgncaIon LffcI sur |c ux nIcrnc
p ou x Sortie hexadcimale Utiliser hex
o Sortie octale Utiliser oct
e Format scientifque Mettre les bits des rels
scientifc
f Format virgule fxe Mettre les bits des rels fxed
g Format des rels gnral
(par dfaut)
Invalide tous les bits de champ
pour les rels
X, E ou G Comme pour leurs
quivalents en minuscules
mais utilise des capitales
(exposant, valeurs
hexadcimales, )
Comme x, e, ou g et utiliser
uppercase en plus
d, l ou u Sortie entire Mettre les bits de base dec
280
Caractres de type (Suite)
LaracIcrc SgncaIon LffcI sur |c ux nIcrnc
s ou S Sortie de chane La spcifcation de prcision est
invalide, et la valeur est stocke
pour une troncature ventuelle
(voir lexplication sur prcision
ci-dessus)
c ou C Sortie dun caractre Seul le premier caractre de la
conversion en chane est utilis
% Affcher le caractre % N/A
Convertir une donne en chane
de caractres
#include <boost/lexical_cast.hpp>
class bad_lexical_cast;
template<typename TDestination, typename TSource>

TDestination lexical_cast(const TSource& arg);


lexical_cast convertit arg en chane de caractres de type
std::string ou std::wstring. Si la conversion choue, une
exception boost::lexical_cast est dclenche.
Pour fonctionner, ce patron requiert des types source et
destination les capacits suivantes :
TSource est redirigeable sur un fux (OutputStreamable).
Un operator<< prenant gauche un std::ostream ou
std::wostream et droite un TSource doit tre dfni ;
TDestination est redirigeable depuis un fux (InputStream
able). Un operator>> prenant gauche un std::istream
ou std::wistream et droite un TDestination doit tre
dfni ;
LonvcrIr unc donncc cn chanc dc caracIcrcs
200 LhAPIJL 18 800SJ
TSource et TDestination doivent avoir un constructeur
par copie ;
TDestination doit avoir un constructeur par dfaut.
Le type caractre du fux sous-jacent est suppos tre de
type char moins que TSource ou TDestination requiert un
type caractre tendu. Les types TSource ncessitant un
fux caractre tendu sont wchar_t, wchar_t*, et std::
wstring. Les types TDestination ncessitant un fux carac-
tre tendu sont wchar_t et std::wstring.
Info
Si vos conversions requirent un haut niveau de contrle sur la
manire doprer la conversion, std::stringstream et std::
wstringstream offrent une solution plus approprie.
Si vous ne disposez pas de conversion base sur les fux pour
vos types, lexical_cast nest pas le bon outil. Dailleurs, il
nest pas conu pour ce type de situation.
Lexemple suivant montre comment traiter la ligne dargu-
ment dun programme en tant que donnes numriques :
int main(int argc, char* argv[])
{
std::vector<short> args;
for (int i=1 ; i<argc && argv[i] !=0 ; ++i)
{
try
{
args.push_back( boost::lexical_cast<short>

(argv[i]) );
}
catch(boost::bad_lexical_cast&)
{
args.push_back(0);
}
//
}
}
201
Cet autre exemple illustre lutilisation dune donne num-
rique dans une opration sur des chanes :
void affcher(const std::string&);
void affcher_erreur(int numero)
{
using namespace boost;
affcher(Erreur n + lexical_cast<std::

string>(numero) + );
}
Voici un dernier exemple montrant la conversion dune
chane de caractres vers divers types numriques :
using namespace boost;
//
std::string txt = 28.654;
//
foat a = lexical_cast<foat>(txt);
double b = lexical_cast<double>(txt);
unsigned int c = lexical_cast<unsigned int>(txt);
sdt::string d = lexical_cast<std::string>(16978.3201);
//
Construire et utiliser
une expression rgulire
#include <boost/regex.hpp>
boost::regex er();
bool boost::regex_match(BidirectionalIterator debut,

BidirectionalIterator fn, [boost::match_results

<>& m,] const boost::basic_regex<>& er, boost::

match_fag_type = match_default);
LonsIrurc cI uI|scr unc cxprcsson rcgu|crc
202 LhAPIJL 18 800SJ
bool boost::regex_match(const charT* str, [boost::

match_results<>& m,] const boost::basic_regex<>

& er, boost::match_fag_type = match_default);


bool boost::regex_match(const std::basic_string<>,

[boost::match_results<>& m,] const boost::basic

_regex<>& er, boost::match_fag_type =

match_default);
bool boost::regex_search(BidirectionalIterator

debut, BidirectionalIterator fn, [boost::match

_results<>& m,] const boost::basic_regex<>& er,

boost::match_fag_type = match_default);
bool boost::regex_search(const charT* str,

[boost::match_results<>& m,] const boost::

basic_regex<>& er, boost::match_fag_type =

match_default);
bool boost::regex_search(const std::basic_string<>,

[boost::match_results<>& m,] const boost::

basic_regex<>& er, boost::match_fag_type =

match_default);
La classe boost::regex permet de construire une expres-
sion rgulire que lon utilise ensuite avec lune des deux
autres fonctions fournies.
Lalgorithme boost::regex_match() dtermine si une
expression rgulire correspond lensemble des caract-
res dune squence fournie (par une paire ditrateurs
bidirectionnels). Le plus souvent, cet algorithme est utilis
pour valider des donnes utilisateurs. la place dune
squence, vous pouvez aussi fournir une chane de carac-
tres simple ou Unicode, style C ou C++. Fournir une
variable pour rcuprer linformation de correspondance
est optionnel.
208
Lexemple suivant utilise les expressions rgulires pour
dcoder le message de rponse dun serveur FTP :
boost::regex expr(([0-9]+)(\\-
|

|
$)(.*));
int decoder_msg_FTP(const char* reponse, std::string* msg)
{
boost::cmatch correspondance;
if (boost::regex_match(reponse, correspondance, expr))
{
// correspondance[0] contient la chane complte
// correspondance[1] contient le code de rponse
// correspondance[2] contient le sparateur
// correspondance[3] contient le message
if (msg)
msg->assign( correspondance[3].frst,

correspondance[3].second );
return std::atoi( correspondance[1].frst );
}
// pas de correspondance trouve
if (msg)
msg->erase();
return -1;
}
Lalgorithme boost::regex_search() recherche une sous-
chane correspondant lexpression rgulire donne. Cet
algorithme utilise diverses heuristiques pour rduire le
temps de recherche, notamment si la possibilit de trouver
une correspondance la position courante est forte.
Lexemple ci-aprs recherche toutes les chanes de carac-
tres C dans un fchier source pralablement charg
comme chane de caractres :
boost::regex chaine_c((\)([^\]*)(\));
void chaines_c(const std::string& contenu_fchier)
{
std::string::const_iterator debut =

contenu_fchier.begin(), fn = contenu_fchier.end();
boost::match_results<std::string::const_iterator> quoi;
LonsIrurc cI uI|scr unc cxprcsson rcgu|crc
204 LhAPIJL 18 800SJ
boost::match_fag_type fags = boost::match_default;
while (boost::regex_search(debut,fn,quoi,chaine_c,fags))
{
std::string str( quoi[1].frst, quoi[1].second );
std::cout << Trouv : << str << std::endl;
// mise jour de la position
debut = quoi[0].second;
// mise jour des options
fags
|
= boost::match_prev_avail;
fags
|
= boost::match_not_bob;
}
}
Caractres spciaux des expressions rgulires
0pcraIcur
1
0cscrpIon
. Nimporte quel caractre
x* 0, 1, 2, fois le caractre x
x+ 1, 2, 3, fois le caractre x
x? 0 ou 1 fois le caractre x
x
|
y x ou y
(x) x
[xy] x ou y (ensemble de caractres)
[x-y] x, y, ou z (intervalle de caractres)
[^x] nimporte quel caractre diffrent de x
\x x, mme si x est un caractre oprateur
x{n} n fois x
x{n,m} n, n+1, , m fois x
1. Sauf indication contraire, x , y ou z sont des expressions
rgulires quelconques. Par exemple, lexpression t* dnote 0
n occurrences du caractre t et lexpression t
|
m)* dnote 0
n occurrences des caractres t ou m. Lexpression correspondant
x est dune complexit quelconque.
205
LaracIcrc spcca| 0cscrpIon
^ En dbut, signife dbut de chane. Par
exemple, ^debut signife toute chane
commenant par dbut .
$ En fn, signife fn de chane. Par exemple,
fn$ signife toute chane fnissant par fn .
viter les pertes mmoire grce
aux pointeurs intelligents
Les pointeurs intelligents sont des objets qui stockent un
pointeur sur des objets allous dynamiquement. Ils fonc-
tionnent de manire analogue aux pointeurs classiques,
except quils suppriment automatiquement les objets
allous au moment opportun. Plus exactement, lorsque
plus aucun pointeur fort ne rfrence un objet donn,
celui-ci est dtruit et tous les pointeurs faibles qui taient
encore lis cet objet deviennent des pointeurs nuls.
AIIcnIon
Mme avec les pointeurs forts, vous pouvez rencontrer des
pertes mmoire. Considrez lexemple suivant :
void f(boost::shared_ptr<int>, int);
int g();
void ok()
{
boost::shared_ptr<int> p(new int(1));
f(p, g());
}
void perte()
{
f(boost::shared_ptr<int>(new int(1)), g());
}
LvIcr |cs pcrIcs mcmorc grcc aux ponIcurs nIc||gcnIs
208 LhAPIJL 18 800SJ
Les fonctions ok() et perte() semblent identiques, et pourtant,
comme leur nom lindique, lune est correcte et lautre peut pro-
voquer une perte mmoire. En effet, la norme du C++ nimpose
pas lordre dvaluation des arguments dune fonction. Ainsi, il
est possible que linstruction new int(1) soit value en pre-
mier, puis que vienne en second g(), pour ne jamais arriver
la construction du shared_ptr si la fonction g() lance une
exception. Lentier ainsi allou ne sera jamais libr !
Utiliser les pointeurs forts
#include <boost/shared_ptr.hpp>
boost::shared_ptr<Type> ptr(new Type);
#include <boost/shared_array.hpp>
boost::shared_array<Type> ptr(new Type[]);
Les pointeurs forts boost::shared_ptr<> offrent le mme
niveau de scurit que les type pointeurs bas niveau vis-
-vis des accs concurrents : aucune (ou presque). Une
instance de shared_ptr peut tre lue simultanment
par plusieurs threads. Diffrentes instances de shared_ptr
peuvent tre modifes (par loprateur = ou la fonction
membre reset()) simultanment par diffrents threads,
et (do le presque) mme si ces diffrentes instances
partagent le mme compteur de rfrence.
// dclaration commune tous les exemples
boost::shared_ptr<int> p(new int(42));
// thread A
shared_ptr<int> p2(p); // lit p
// thread B
shared_ptr<int> p3(p); // OK, lecture simultane correcte
201
// thread A
p.reset(new int(1912)); // modife p
// thread B
p2.reset(); // OK, modife p2
// thread A
p = p3; // lit p3, modife p
// thread B
p3.reset(); // crit p3; INDEFINI, lecture/modif.

simultane
// thread A
p3 = p2; // lit p2, modife p3
// thread B
// p2 devient hors datteinte: INDEFINI, le

destructeur est considr comme une modifcation


// thread A
p3.reset(new int(1));
// thread B
p3.reset(new int(2)); // INDEFINI, modifcation simultane
Info
La classe boost::shared_ptr<> ne peut tre utilise que sur
des objets simples. Comment faire si vous avez allou un
tableau dobjets ? Dans ce cas, vous avez votre disposition la
classe suivante : boost::shared_array<>, disponible dans
<boost/shared_array.hpp>.
LvIcr |cs pcrIcs mcmorc grcc aux ponIcurs nIc||gcnIs
208 LhAPIJL 18 800SJ
Utiliser les pointeurs faibles
#include <boost/weak_ptr.hpp>
boost::weak_ptr<Type> ptr(boost::shared_ptr<Type>);
Les pointeurs faibles (boost::weak_ptr<>) stockent une
rfrence sur un pointeur fort. Mais du coup, leur utilisa-
tion nest pas sre, car lobjet sous-jacent peut tre libr
tout moment, comme le montre lexemple suivant :
boost::shared_ptr<int> p(new int(10));
boost::weak_ptr<int> q(p);
//
if (!q.expired())
{
// ici q est non nul, mais peut pointer sur nimporte

quoi
// si lobjet a t libr entre temps cause dun

autre
// thread excutant par exemple p.reset().
}
Pour cela, il sufft de convertir momentanment le poin-
teur faible en fort :
boost::shared_ptr<int> p(new int(10));
boost::weak_ptr<int> q(p);
//
if (boost::shared_ptr<int> r = q.lock())
{
// ici lutilisation r (par *r ou r->) est sre
}
200
Utiliser les pointeurs locaux
#include <boost/scoped_ptr.hpp>
boost::scoped_ptr<Type> ptr(new Type);

#include <boost/scoped_array.hpp>
boost::scoped_array<Type> ptr(new Type[]);
Les pointeurs locaux boost::scoped_ptr<> et boost::
scoped_array<> sont comme des pointeurs forts existence
unique. Ils ne peuvent tre copis, et donc nont pas besoin
de grer de compteur de rfrence. quoi sont-ils donc
utiles ? Non grer des singletons mais associer simple-
ment un objet un autre, comme le montre lexemple
ci-aprs. Ou bien encore, servir assurer la destruction
dobjets allous localement. Nhsitez pas utiliser ce type
de pointeur intelligent, car de par sa simplicit intrinsque,
il ne conduit aucune perte de performance.
class MaClasse
{
boost::scoped_ptr<int> ptr;
public:
MaClasse() : ptr(new int) { *ptr=0; }
//
};
Mettre en uvre des pointeurs (forts) instrusifs
#include <boost/intrusive_ptr.hpp>
boost::intrusive_ptr<Type> ptr(Type*);
boost::intrusive_ptr<Type> ptr(Type*,false);
LvIcr |cs pcrIcs mcmorc grcc aux ponIcurs nIc||gcnIs
800 LhAPIJL 18 800SJ
Les boost::intrusive_ptr<> permettent de stocker des
pointeurs vers des objets possdant dj un compteur de
rfrence. Cette gestion se fait par lintermdiaire dappels
aux fonctions intrusive_ptr_add_ref(Type*) et intrusive_
ptr_release(Type*), quil vous appartient de surcharger.
Si vous ne savez pas quoi utiliser, entre pointeurs fort et
intrusif, commencez par tester si les pointeurs forts
conviennent votre besoin.
Crer des unions de types
scurises
#include <boost/variant.hpp>
boost::variant<Type1,Type2,> variable;
U * boost::get(variant<T1, T2, , TN> * operand);
const U* boost::get(const variant<T1, T2, , TN>*

operand);
U& boost::get(variant<T1, T2, , TN>& operand);
const U& boost::get(const variant<T1, T2, , TN>&

operand);
La classe boost::variant<> permet de runir plusieurs types
de donnes en un seul, de manire sre, simple et effcace.
Runir ne signife pas que lon stocke un objet de chacun
des types, mais un seul objet de lun des types spcifs.
Cela permet de crer une sorte de type gnrique pou-
vant stocker un objet dun type ou dun autre. Lexemple
suivant montre comment utiliser cette solution :
#include <boost/variant.hpp>
#include <iostream>

struct visiteur_entier : public boost::static_visitor<int>
801
{
// si le variant est un entier
int operator()(int i) const
{
return i; // rien faire
}

// si cest une chane
int operator()(const std::string& s) const
{
return s.length(); // le convertir en sa longueur
}
};
int main()
{
boost::variant< int, std::string > u(bonjour);
std::cout << u; // u est une chane, affche : bonjour

int r = boost::apply_visitor( visiteur_entier(), u );
std::cout << r; // affchera la longueur de la chane
// contenu dans le variant, soit : 7
}
Un autre moyen, peut-tre plus simple mais moins puis-
sant (car neffectuant aucune conversion) est dutiliser la
fonction boost::get<>().
Lexemple suivant montre comment la mettre en uvre
dans vos programmes :
void fois_trois( boost::variant< int, std::string >& v)
{
if (int* i_ptr = boost::get<int>(&v))
*i_ptr *= 3;
else if (std::string* s_ptr = boost::get

<std::string>(&v))
*s_ptr = (*s_ptr) + (*s_ptr) + (*s_ptr);
}
Lrccr dcs unons dc Iypcs sccursccs
802 LhAPIJL 18 800SJ
Mais l encore, si lon ajoute un type supplmentaire, il est
facile doublier dajouter le code ncessaire. La robustesse
ce niveau rside plutt dans la manire dcrire un visi-
teur : en utilisant les templates et en se basant sur un op-
rateur ou une fonction commune aux diffrents types
prsent dans le variant. Lexemple suivant lillustre travers
un visiteur utilisant loprateur += :
struct fois_deux_generic : boost:: static_visitor<>
{
template <typename T>
void operator()(T& v) const
{
v += v;
}
};
//
std::vector< boost::variant<int, std:: string> > V;
V.push_back( 21 );
V.push_back( bonjour );
fois_deux_generic visiteur;
std::for_each(V.begin(), V.end(),

boost::apply_visitor(visiteur));
// V == { 42, bonjour bonjour }
Info
En programmation, il est bien souvent utile de manipuler des
types distincts comme sil sagissait dun seul. En C++, on
retrouve cet aspect avec les unions de types (union, voir la
section Types labors du Chapitre 1). Lexemple suivant en
montre un bref rappel :
union { int i; double d; } nombre;
nombre.d = 3.141592654;
nombre.i = 12; // crase nombre.d
Malheureusement, cette technique devient inoprante ds que
lon se replace dans un contexte orient objet. Les unions de type
(union) arrivent en effet directement de lhritage du langage C.
808
Par voie de consquence, ils ne supportent que des types primaires
ou primaires composs, et ne supportent donc pas la construction
ou la destruction dobjet non triviaux. Lexemple suivant illustre
clairement cette limitation des unions de type (union) :
union
{
int i;
std::string s; // ne fonctionne pas, nest pas trivial
} u;
Une nouvelle approche est donc requise. Vous trouverez, si vous
ne les avez pas dj rencontres, des solutions bases sur :
l'allocation dynamique ;
un type de base commun et l'utilisation de fonctions
virtuelles ;
des pointeurs non typs void* (le pire des cas).
Les objets rels sont souvent, dans ces solutions, retrouvs laide
de transtypage comme dynamic_cast, boost::any_cast, etc.
Toutefois, ces solutions sont fortement sujettes erreurs, telles :
les erreurs de downcast ne sont pas dtectes la compi-
lation. Une erreur de ce genre ne peut donc se dtecter
que durant lexcution ;
l'ajout de nouveaux types concrets est ignor. Si un nouveau
type concret est ajout la hirarchie, les downcasts
existants continueront de fonctionner tel quels, tout en
ignorant royalement lexistence de ce nouveau type. Le
programmeur doit donc trouver de lui-mme tous les
emplacements de codes modifer. Beaucoup de temps
passer et beaucoup derreurs en perspective
De plus, mme bien implmentes, ces solutions resteront
pnalises par le cot de labstraction laquelle elles font
appel. Ce cot se retrouve dans lappel des fonctions virtuelles
et des transtypages dynamiques.
Lrccr dcs unons dc Iypcs sccursccs
804 LhAPIJL 18 800SJ
Parcourir un conteneur
avec BOOST_FOREACH
BOOST_FOREACH(type element, conteneur)
{
//
}
En C++, crire une boucle peut parfois savrer fastidieux.
Utiliser les itrateurs, avec leurs dclarations templatises
rallonge, peut facilement alourdir lcriture et donc la lisi-
bilit. Lalgorithme std::foreach() quant lui oblige
dplacer tout le bloc de code dans un prdicat. Si cela peut
tre trs pratique pour une utilisation rcurrente dun
mme prdicat, cela lest beaucoup moins pour du ponc-
tuel ou du spcifque.
BOOST_FOREACH est conu pour la facilit dutilisation et
leffcacit : pas dallocation dynamique, pas dappel de
fonction virtuelle ou de pointeur de fonction, ni dappel
qui ne puisse tre optimis par le compilateur. Le code
produit est proche de loptimal que lon aurait obtenu en
codant la boucle soi-mme. Bien qutant une macro,
celle-ci se comporte sans surprise : ses arguments ne sont
valus quune seule fois.
#include <string>
#include <iostream>
#include <boost/foreach.hpp>

//
std::string chaine( Bonjour );
BOOST_FOREACH( char ch, chaine )
{
std::cout << ch;
}
805
BOOST_FOREACH parcourt les squences, en se basant sur
boost::range, comme par exemple :
les conteneurs STL ;
les tableaux de type C ;
les chanes zro terminal (char et wchar_t) ;
une std::pair ditrateurs.
Vous trouvez qucrire BOOST_FOREACH est trop long ?
Que lcriture en capitale dimprimerie nest pas votre
got ? Possible, mais cela nen reste pas moins le standard
adopt travers les conventions de nommage de la
bibliothque BOOST. Il nappartient qu vous de le
renommer ainsi :
#defne foreach BOOST_FOREACH
Attention toutefois de ne pas causer un confit de nom
dans votre code.
AIIcnIon
Nutilisez pas #defne foreach(x,y) BOOST_FOREACH(x,y) :
cela posera problme lors dune utilisation avec des macros
comme paramtres, provoquant une cration de code suppl-
mentaire lors de linterprtation. Utilisez plutt la technique
prcite.
Parcourr un conIcncur avcc BOOST_FOREACH
808 LhAPIJL 18 800SJ
Gnrer des messages derreur
pendant le processus de
compilation
#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT( condition )
La macro BOOST_STATIC_ASSERT(x) permet de gnrer des
messages derreur pendant le processus de compilation si
lexpression constante x est fausse. Elle est lquivalent des
macros dassertion classiques, mais contrairement ces
dernires qui se dclenchent pendant lexcution du pro-
gramme, celles-ci se dclenchent pendant la compilation.
Les concepteurs de cette partie de BOOST ont choisi de
nommer ce type dassertion des assertions statiques (
loppos de dynamique). Notez que si la condition est
true, alors aucun code nest gnr par cette macro. Si elle
est utilise au sein dun template, elle sera value lors de
linstanciation de ce dernier. Ceci est particulirement
utile pour vrifer certaines conditions sur les paramtres
templates.
Lun des atouts principaux de BOOST_STATIC_ASSERT() est
de gnrer des messages derreur humainement lisibles.
Ils indiquent ainsi immdiatement et clairement si le
code dune bibliothque (ou votre code) est mal utilis.
Laffchage peut varier dun compilateur un autre, mais il
devrait ressembler ceci :
Illegal use of STATIC_ASSERTION_FAILURE<false>
Vous pouvez utiliser BOOST_STATIC_ASSERT() au mme
endroit que nimporte quelle dclaration : dans une classe,
une fonction ou un espace de noms.
801 0cncrcr dcs mcssagcs dcrrcur pcndanI |c proccssus dc comp|aIon
Lexemple ci-aprs permet de contrler que le type int est
cod sur au moins 32 bits, et que le type wchar_t est bien
non sign :
#include <climits>
#include <cwchar>
#include <limits>
#include <boost/static_assert.hpp>

namespace mes_conditions
{
BOOST_STATIC_ASSERT(std::numeric_limits<int>::

digits >= 32);


BOOST_STATIC_ASSERT(WCHAR_MIN >= 0);
}
Lors de lcriture de template, il est intressant de pouvoir
tester si les paramtres fournis vrifent bien certaines
conditions. Cela permet, en partie, de garantir le bon
fonctionnement de la fonction gnrique criture. Sinon,
cela apporte au moins lavantage dobtenir des message
derreur plus explicites quun traditionnel message relatif
un problme de syntaxe Lexemple ci-aprs montre
comment utiliser BOOST_STATIC_ASSERT() pour tre certain
quun message derreur explicite apparaisse lorsquon utilise
un mauvais type ditrateur avec un algorithme donn.
#include <iterator>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>

template <class RandomAccessIterator >
RandomAccessIterator mon_algorithme(
RandomAccessIterator from,
RandomAccessIterator to)
{
// cet algorithme ne doit tre utilis quavec des
808 LhAPIJL 18 800SJ
// itrateurs accs direct (ou random access

iterator)
typedef typename std::iterator_traits<

RandomAccessIterator >::iterator_category cat;


BOOST_STATIC_ASSERT((boost::is_convertible<cat,

const std::random_access_iterator_tag&>::value));
//
// implmentation
//
return from;
}
AsIucc
Les doubles parenthses de lexemple prcdent ont pour but
dtre certain que la virgule ne soit pas prise comme sparateur
dargument de macro.
Lexemple ci-aprs montre lutilisation de BOOST_STATIC_
ASSERT() avec les classes templates. Il expose un moyen de
vrifer que le paramtre soit au moins un type entier,
sign, et sur au moins 16 bits.
#include <climits>
#include <boost/static_assert.hpp>

template <class UnsignedInt>
class MaClasse
{
private:
BOOST_STATIC_ASSERT(

(std::numeric_limits<UnsignedInt>::digits >= 16)


&& std::numeric_limits<UnsignedInt>::is_specialized

&& std::numeric_limits<UnsignedInt>::is_integer

&& !std::numeric_limits<UnsignedInt>::is_signed);
public:
//
};
800 0cncrcr dcs mcssagcs dcrrcur pcndanI |c proccssus dc comp|aIon
AIIcnIon
Certains compilateurs ont parfois tendance en faire trop.
Thoriquement, les assertions statiques prsentes dans une
classe ou une fonction template ne sont pas instancies tant
que le template dans lequel elles apparaissent nest pas instan-
ci. Pourtant, il existe un cas un peu part : lorsque lassertion
statique ne dpend pas dau moins un paramtre template,
comme ci-aprs :
template <class T>
struct ne_peut_pas_etre_instancie
{
BOOST_STATIC_ASSERTION(false); // ne dpend

daucun paramtre template


};
Dans ce cas, lassertion statique peut tre value mme si la
classe nest jamais instancie. Cest le cas avec, au moins, les
compilateurs Intel 8.1 et gcc 3.4. Un moyen de palier cet incon-
vnient est de rendre lassertion dpendante dun paramtre
template. Lexemple suivant montre comme le faire, laide de
linstruction sizeof() :
template <class T>
struct ne_peut_pas_etre_instancie
{
BOOST_STATIC_ASSERTION(sizeof(T)==0); // dpendant

dun paramtre template


};

14
ProgrammaIon
mu|IIhrcad avcc 0J
Les threads sont maintenant trs rpandus. Il existe diver-
ses bibliothques permettant de les apprhender facile-
ment. BOOST fournit une bibliothque haut niveau pour
les crer et les utiliser, wxWidgets une autre. Dans cet
ouvrage, jai choisi dutiliser ceux de QT.
Crer un thread
#include <QThread>
class MonThread : public Qthread
{
Q_OBJECT
public:
void run() { }
};
Pour crer un thread avec QT, il sufft de driver la classe
QThread et de rimplmenter la fonction membre run() de
cette dernire. Ensuite, il sufft de crer une instance de
votre nouvelle classe et dappeler la fonction membre
start() pour excuter le contenu de la fonction run()
dans un nouveau thread.
812 LhAPIJL 14 ProgrammaIon mu|IIhrcad avcc 0J
Il existe une contrainte avec les threads QT : il est imp-
ratif de crer un objet QApplication ou QCoreApplication
avant de crer un QThread.
Partager des ressources
#include <QSharedMemory>
QSharedMemory sm(const QString& clef, QObject*=0);
QSharedMemory sm(QObject*=0);
bool QSharedMemory::create(int taille, AccessMode

mode = ReadWrite);
int QSharedMemory::size() const;
bool QSharedMemory::attach(AccessMode mode =

ReadWrite );
bool QsharedMemory::detach();
bool QSharedMemory::isAttached() const;
const void* QSharedMemory::constData() const;
void* QSharedMemory::data();
bool QSharedMemory::lock();
void* QSharedMemory::unlock();
QSharedMemory fournit un accs un segment de mmoire
partag par plusieurs threads ou processus. Cette classe
procure aussi un moyen simple de bloquer cette mmoire
en accs exclusif. Lorsque vous utilisez cette classe, il faut
tre conscient quil existe des diffrences dimplmenta-
tion en fonction de la plate-forme sur laquelle vous utili-
sez la bibliothque QT.
Sous Windows, la classe ne possde pas le segment de
mmoire. Quand tous les threads et processus ayant un
lien avec ce segment de mmoire rserv ont dtruit leur
instance de QSharedMemory ou se sont termins, alors le
noyau de Windows libre le segment de mmoire auto-
matiquement.
818
Sous Unix, QSharedMemory possde le segment de mmoire.
Le comportement est le mme que sous Windows en ce sens
que cest toujours le noyau du systme qui libre le segment.
Mais, si lun des threads ou des processus concerns plante, il
se peut que le segment de mmoire ne soit jamais libr.
Sous HP-UX, un processus ne peut tre li quune fois sur
un segment mmoire. Du coup, vous devrez vous-mme
grer les accs concurrentiels ce segment entre les diff-
rents threads dun mme processus. Dans ce contexte,
QSharedMemory ne pourra pas tre utilis.
Utilisez lock() et unlock() lorsque vous lisez ou crivez
des donnes du segment de mmoire partage.
Se protger contre laccs
simultan une ressource
avec les mutex
#include <QMutex>
QMutex m(mode); // == NonRecursive par dfaut
m.lock();
bool r = m.tryLock();
bool r = m.tryLock(timeout);
m.unLock();
Les mutex permettent de se prmunir contre laccs et/ou
la modifcation dune ressource (mmoire, objet, driver, )
par plusieurs threads en mme temps. Cela est souvent
essentiel au bon droulement dun programme. Pour
comprendre lintrt dun tel mcanisme, imaginons que
deux fonctions func1() et func2() soient excutes dans des
threads diffrents, en mme temps, et effectuent chacune des
calculs sur la mme variable. Le rsultat serait imprvisible.
Sc proIcgcr conIrc |acccs smu|Ianc a unc rcssourcc avcc |cs muIcx
814 LhAPIJL 14 ProgrammaIon mu|IIhrcad avcc 0J
Lexemple ci-aprs montre comment protger laccs
cette variable pour viter quelle soit modife et utilise
par plusieurs threads en mme temps.
QMutex m;
double variable = 20.0;

void func1()
{
m.lock();
variable *= 10.0;
variable += 3.0;
m.unLock();
}

void func2()
{
m.lock();
variable -= 100.0;
variable /= 34.0;
m.unLock();
}
Nous lavons dit, un mutex sert protger un objet (ici
une variable) contre des accs concurrentiels. Pour quoi
cela ? Simplement pour viter des comportements impr-
visibles, dans le meilleur des cas, ou des plantages alatoires
et trs diffciles cerner dans le pire des cas. Pour com-
prendre ce risque, imaginez que lexemple prcdent ne
contienne aucune protection par mutex. Dans ce cas,
lexcution du code pourrait se passer comme suit :
// thread 1 excutant func1
variable *= 10.0; // 200
// thread 2 excutant func2
variable -= 100.0; // 100
variable /= 34.0; // 100/34 = 2 + 16/17
// thread 1 excutant func1
variable += 3.0; // 5 + 16/17
815
Lutilisation du mutex empchera func2() de commencer
ses calculs avant que func1() nait fni les siens.
// thread 1 excutant func1
variable *= 10.0; // 200
variable += 3.0; // 203
// thread 2 excutant func2
variable -= 100.0; // 103
variable /= 34.0; // 103/34 = 3 + 1/34
Cet exemple est trivial mais permet de bien comprendre
le mcanisme mis en jeu.
AsIucc
Souvent, les fonctions prsentent un code bien plus complexe,
avec plusieurs instructions return dissmines a et l, sans
oublier les lancements dexceptions ou les appels dautres
fonctions pouvant elles aussi dclencher dautres exceptions. Du
coup, il peut devenir dlicat de noublier aucune libration dun
mutex. Pour cela, nous pourrions crire nous-mme une classe
lie au mutex qui nous intresse et laisser le soin son destruc-
teur de librer ledit mutex. Or la bibliothque de QT fournit dj
cette petite merveille : QMutexLocker. Lexemple ci-aprs vous
montre comment lutiliser avec la premire fonction. Mme sil
reste trivial, il expose lessentiel de ce quil faut savoir :
#include <QMutexLocker>
void func1()
{
QMutexLocker(&m);
variable *= 10.0;
variable += 3.0;
// ici le destructeur de QMutextLocker appelle

m.unLock()
}
Ainsi, adieu les risques dsastreux doubli de libration de mutex !
Sc proIcgcr conIrc |acccs smu|Ianc a unc rcssourcc avcc |cs muIcx
818 LhAPIJL 14 ProgrammaIon mu|IIhrcad avcc 0J
Contrler le nombre daccs
simultans une ressource
avec les smaphores
#include <QSemaphore>
QSemaphore s(n); // n = 0 si omis
void QSemaphore::acquire(n); // n = 1 si omis
int QSemaphore::available() const;
void QSemaphore::release(n) // n = 1 si omis
bool QSemaphore::tryAcquire(n); // n = 1 si omis
bool QSemaphore::tryAcquire(n, tempsLimite);
Les smaphores sont un peu comme des mutex mais peu-
vent permettre plusieurs threads dutiliser en mme
temps les ressources quelles protgent. On pourrait voir
une smaphore comme un agent de location qui dispose
de n (valeur donne au constructeur de la classe) ressour-
ces, comme des vlos par exemple. Un client peut louer
un ou plusieurs vlos dun coup (par lappel acquire(v))
et les rendre dun coup ou par lot (par un ou plusieurs
appels release(w)).
Un appel acquire() oblige se placer dans une fle
dattente jusqu ce que le nombre de ressources deman-
des soient disponibles. Si le smaphore nen dispose pas
dautant, je vous laisse deviner le problme il risque
fort de bloquer tout le monde. Du coup et pour viter ce
problme, vous disposez galement de deux autres
mthodes :
tryAcquire(n) pour tenter dacqurir n ressources ou
partir sil ny en a pas. Le client devra patienter de lui-
mme en dehors de la fle dattente de la boutique et
retenter sa chance plus tard ;
811
tryAcquire(n,tempsLimite) pour demander n ressources
et se placer dans la fle dattente. Mais si le client nest
pas servi avant le tempsLimite (en millisecondes) donn,
il dcide de sortir de la fle dattente (et de perdre sa
place) pour poursuivre son chemin.
Info
Avec les smaphores, vous pouvez commencer avec un nombre
de ressources nul (gal zro). Librer une ou plusieurs res-
sources revient alors lui en allouer autant. Ce comportement
est valable tout moment. Cette implmentation ne gre donc
pas de test sur un maximum de ressource que lon dfnirait
la cration dun smaphore. Le code suivant illustre ce fait :
QSemaphore s(3); // s.available() == 3
s.acquire(1); // s.available() == 2
s.acquire(2); // s.available() == 0
s.release(4); // s.available() == 4, on a dpass 3
s.release(5);
// s.available() == 9, on en alloue donc bien en plus

AIIcnIon
Si vous oubliez de librer des ressources ou que vous en deman-
dez trop par rapport leur disponibilit, vous provoquerez un
deadlock. Prenez-y garde ds la conception de vos algorithmes.
Nattendez pas de les voir apparatre dans vos tests.
Le deadlock peut aussi parfois survenir lorsque lon oublie de
protger ses ressources avec un mutex ou un smaphore. Du
coup, des variables peuvent avoir t modifes sans quon le
veuille et notre programme se mettre en attente ou en boucle
infnie
LonIr|cr |c nomhrc dacccs smu|Iancs a unc rcssourcc avcc |cs scmaphorcs
818 LhAPIJL 14 ProgrammaIon mu|IIhrcad avcc 0J
Prvenir le compilateur de
lutilisation dune variable
dans plusieurs threads
volatile Type variable; // global, local ou membre

de classe.
Le mot-cl volatile permet de prvenir le compilateur
que cette variable va tre utilise dans plusieurs threads
diffrents. Cela lui permet de la traiter de manire spciale,
notamment lorsque lon utilise les options de compilation
relatives loptimisation.
Ce qualifcateur indique que la variable ou lobjet peut
tre modif par une interruption matrielle, par un autre
programme, un autre processus ou un autre thread. Cela
implique de devoir recharger systmatiquement la variable
chaque fois quelle est utilise, mme si elle se trouve
dj dans un des registres du processeur, ce qui explique le
traitement spcial de ce type de variables vis--vis des
optimisations de programmes ralises par le compilateur.
15
8asc dc donnccs
Les bases de donnes sont couramment utilises en pro-
grammation. Ce chapitre vous prsente quelques outils de
base selon une approche multisystme.
Nous avons mis laccent sur SQLite en raison de sa simplicit
demploi et de sa popularit grandissante. Vous pouvez en
tlcharger les sources sur http://www.sqlite.org. La pre-
mire section vous aidera dterminer si SQLite rpond
vos besoins, les suivantes le mettre en uvre. Les dernires
sections vous permettront dutiliser les bases de donnes avec
un pilote ODBC et la bibliothque graphique wxWidgets.
AsIucc
Afn de rester le plus multiplate-forme possible, prfrez un sys-
tme grant directement les requtes SQL.
Voici quelques sites que je vous invite prendre en consi-
dration :
http://sql.1keydata.com/fr. Pour retrouver la syntaxe
dune requte SQL.
http://dev.mysql.com/doc/refman/5.1/en/tutorial
.html. Pour apprendre mettre en uvre MySQL.
820 LhAPIJL 15 8asc dc donnccs
http://www.sqlapi.com. SQLAPI++ est une API
C++ permettant daccder diverses bases de donnes
SQL (Oracle, SQL Serveur, DB2, Sybase, Informix,
Interbase, SQLBase, MySQL, PostgreSQL, ODBC et
SQLite). SQLAPI++ utilise les API natives des moteurs
de bases de donnes concernes et sexcute donc rapi-
dement et effcacement. Cette bibliothque fournit
galement une interface bas niveau permettant dacc-
der des caractristiques particulires des bases de don-
nes. En encapsulant les API des divers moteurs,
SQLAPI++ agit comme un intergiciel (middleware) et
favorise la portabilit. Elle est disponible pour les syst-
mes Win32, Linux et Solaris, et au moins les compila-
teurs Microsoft Visual C++, Borland C++ Builder,
GNU g++. Cette bibliothque est un shareware.
http://wxcode.sourceforge.net/components/
wxsqlite3. Pour utiliser SQLite avec wxWidgets.
http://sqlitepp.berlios.de. Pour les puristes du C++,
voici une bibliothque C++ encapsulant celle de SQLite.
http://debea.net. Debea (DataBasE Access library) est
une collection dinterfaces permettant de connecter
des objets C++ diverses bases de donnes. Cette
bibliothque ne cherche pas supprimer les requtes
SQL, mais gnre automatiquement certaines dentre
elles, acclrant dautant votre vitesse de dveloppe-
ment. Disponible pour Linux (g++ 3.6 ou plus),
Windows 98/2000/XP (VC++ 2003 et 2005). Cette
bibliothque possde galement une interface pour
wxWidgets : wxDba.
http://www.oracle.com/technology/software/
products/database/index.html. Oracle est prsent
gratuit pour coder des prototypes dapplication (non
commercialiss, non utiliss intensivement en tant
821
quoutil interne). Disponible pour Windows (32 et
64 bits), Linux (32 et 64 bits), Solaris (SPARC) 64 bits,
AIX (PPC64), HP-UX (Itanium et PA-RISC).
Savoir quand utiliser SQLite
SQLite est diffrent de la plupart des autres systmes de
bases de donnes SQL. Il a dabord t conu pour tre
simple :
administrer ;
utiliser ;
embarquer dans un programme ;
maintenir et personnaliser.
SQLite est apprci parce quil est petit, rapide et stable. Sa
stabilit dcoule de sa simplicit (moins de fonctionnalits,
moins de risques derreur). En revanche, pour atteindre ce
niveau de simplicit, il a fallu sacrifer des fonctionnalits
qui, dans certains contextes, sont apprciables, comme la
possibilit de faire face une forte demande daccs simul-
tans (high concurrency), une gestion fne des contrles dac-
cs, la mise disposition dun large ensemble de fonctions
intgres, les procdures stockes, lvolution vers le tra-
pta-octet, etc. Si vous avez besoin de telles fonctionnalits
et que la complexit quelles induisent ne vous fait pas
peur, alors SQLite nest probablement pas pour vous.
SQLite ne prtend pas concurrencer Oracle ou
PostgreSQL. Il na pas t conu (a priori) pour tre le
moteur de base de donnes de toute une entreprise.
La rgle de base pour dterminer sil convient vos besoins
est est la suivante : prfrez SQLite lorsque la simplicit
dadministration, de mise en uvre et de maintenance est
plus importante que les innombrables (et complexes)
Savor quand uI|scr S0LIc
822 LhAPIJL 15 8asc dc donnccs
fonctionnalits que les systmes de bases de donnes dentre-
prise fournissent. Il se trouve que les situations o la simpli-
cit est primordiale sont bien plus courantes que ce que lon
peut croire.
Info
SQLite savre aussi tre un moyen de grer des fchiers, en
remplacement de la fonction C fopen().
Cas demploi de SQLite
Format de fchier dune application
SQLite est utilis avec beaucoup de succs comme un
format de fchier disque pour des applications bureau-
tiques telles que outils danalyse fnancire, progiciels
CAD, progiciels de suivi de dossiers, etc. Les opra-
tions traditionnelles douverture de fchiers effectuent
en ralit un sqlite3_open() suivi de lexcution dun
BEGIN TRANSACTION pour verrouiller laccs au contenu.
La sauvegarde fait un COMMIT suivi dun autre BEGIN
TRANSACTION. Lusage des transactions garantit que les
mises jour des fchiers de lapplication sont atomi-
ques, durables, isoles et cohrentes.
Des dclencheurs (triggers) temporaires peuvent tre
ajouts la base de donnes pour enregistrer toutes les
modifcations dans une table temporaire de annu-
ler/refaire . Ces changements peuvent ensuite tre
lus lorsque lutilisateur appuie sur les boutons Annu-
ler et Refaire . Grce cette technique, et sans
limitation de la profondeur de lhistorique des annu-
ler/refaire , la mise en uvre de cette fonctionnalit
peut tre faite laide de trs peu de code.
828
Dispositifs et applications embarques
Une base SQLite requrant peu ou pas dadministra-
tion, SQLite est un bon choix pour les dispositifs ou
services devant fonctionner sans surveillance et sans
intervention humaine. SQLite est adapt pour une
utilisation dans les tlphones cellulaires, les assistants
numriques (PDA), les botes noires et autres appa-
reils. Il fonctionne aussi en tant que base de donnes
embarque dans des applications tlchargeables.
Sites web
SQLite fonctionne habituellement bien comme
moteur de base de donnes de sites web faible ou
moyen trafc (cest--dire plus de 99 % des sites). La
quantit de trafc que SQLite peut traiter dpend bien
sr de la faon dont le site fait usage de ses bases de
donnes. De manire gnrale, tout site recevant
moins de 100 000 visites par jour devrait fonctionner
correctement avec SQLite. Cette limite est une esti-
mation prudente, et non une limite suprieure infran-
chissable. Certains sites atteignant un nombre de
visites dix fois suprieur fonctionnent parfaitement
avec SQLite.
Remplacement de fchiers propritaires
Beaucoup de programmes utilisent fopen(), fread(),
et fwrite() pour crer et manipuler des fchiers de
donnes dans des formats propritaires. SQLite fonc-
tionne particulirement bien pour remplacer ces
fchiers propritaires.
Bases de donnes temporaires
Pour les programmes qui doivent fltrer ou trier un
grand nombre de donnes, il est souvent plus facile et
plus rapide de charger un modle mmoire de base de
Las dcmp|o dc S0LIc
824 LhAPIJL 15 8asc dc donnccs
donnes SQLite et dutiliser des requtes avec jointu-
res et des clauses ORDER BY pour extraire des donnes
dans la forme et lordre dsir plutt que de devoir
coder soi-mme ces fonctionnalits la main. Utiliser
une base de donnes SQL de cette manire permet
galement une plus grande souplesse, car de nouvelles
colonnes et index peuvent tre ajouts sans avoir
recoder chaque requte.
Outils danalyse de donnes en ligne de commande
Ceux qui sont expriments en SQL peuvent utiliser
les programmes en ligne de commande fournis par
SQLite pour analyser divers jeux de donnes. Les
donnes brutes peuvent tre importes de fchiers
CSV, puis dcoupes et groupes pour gnrer une
multitude de rapports. Ce type dutilisation inclut
lanalyse des fchiers logs des sites web, lanalyse de
statistiques sportives, la compilation de mtrique de
code source ou lanalyse de rsultats exprimentaux.
Vous pouvez bien entendu faire de mme avec des
bases de donnes client/serveur professionnelles.
SQLite restera toutefois dans ce cas bien plus facile
mettre en place dans le cadre de fchiers simples, sur-
tout si vous souhaitez les partager avec dautres per-
sonnes (via une cl USB, une pice jointe un courrier
lectronique, etc.).
Base locale pour tests ou dmos
Si vous crivez une application cliente pour un
moteur de base de donnes dentreprise, il est logique
dutiliser une interface dorsale (backend) pour vous
permettre de vous connecter nimporte quel type de
bases de donnes SQL. Dans ce cadre, il est encore
plus logique et bnfque dinclure (en dition de lien
statique) le support de SQLite dans la partie cliente.
825
De cette faon, le programme client pourra tre uti-
lis comme un programme autonome avec des fchiers
de donnes SQLite pour des phases de test ou mme
comme programme de dmonstration.
Enseignement et/ou apprentissage
De par sa simplicit dutilisation, SQLite est un trs
bon moteur de bases de donnes pour apprendre ou
enseigner le langage SQL. En effet, SQLite est trivial
installer : il sufft de copier lexcutable sqlite ou
sqlite.exe sur la machine souhaite et de lutiliser.
Les tudiants (ou vous-mme) peuvent facilement
crer autant de bases de donnes quils le souhaitent
et peuvent envoyer leurs bases de donnes leur pro-
fesseur (ou un collgue) par e-mail. Il est ainsi facile
de les commenter ou de les archiver.
Pour ceux qui sont curieux de comprendre la faon
dont un SGBDR est mis en uvre, la modularit, les
nombreux commentaires et la documentation du
code de SQLite sont apprciables. Cela ne signife pas
que SQLite soit un modle de la faon dont les autres
moteurs de base de donnes sont mis en uvre. Com-
prendre comment fonctionne SQLite permet simple-
ment de comprendre plus rapidement les principes de
fonctionnement des autres systmes.
Exprimentations et prototypes
La simplicit et la modularit de conception de
SQLite en font une plate-forme de choix pour proto-
typer et exprimenter de nouvelles fonctionnalits ou
ides (dutilisation ou dextension du langage SQL
lui-mme).
Las dcmp|o dc S0LIc
828 LhAPIJL 15 8asc dc donnccs
Cas o un autre moteur est plus appropri
Applications client/serveur
Si vous prvoyez que plusieurs applications clientes
accderont travers le rseau (local ou non) une
mme base de donnes, alors orientez-vous plutt
vers un moteur de base de donnes client/serveur
plutt que vers SQLite. Ce dernier fonctionne sur un
systme de fchiers rseau, mais en raison de la latence
associe la plupart de ces systmes, la performance
ne sera pas au rendez-vous. De plus, la logique du
mcanisme de verrouillage de fchier (fle locking) de
nombreux systmes de fchiers contient des bugs (que
ce soit sous Unix ou Windows). Si le verrouillage de
fchiers ne fonctionne pas comme prvu, deux ou
plusieurs clients pourraient alors modifer la mme
partie de la mme base de donnes en mme temps,
entranant une corruption de la base. Comme ce pro-
blme a pour origine la prsence de bugs dans le sys-
tme de fchiers sous-jacent, SQLite ne peut rien faire
pour lempcher.
Une bonne rgle gnrale est dviter dutiliser
SQLite dans des situations o la mme base de don-
nes sera accessible simultanment partir de plu-
sieurs ordinateurs sur un rseau de fchiers.
Trs gros sites web
SQLite fonctionne bien comme systme de base de
donnes pour site web. Mais si votre site devenait lent
et que vous projetiez de dporter la partie base de
donnes sur une deuxime machine, alors vous
devriez srieusement penser utiliser un moteur
client/serveur de type entreprise.
821
Trs grosse base de donnes
Lorsque vous commencez une transaction dans
SQLite, ce qui arrive automatiquement avant chaque
opration qui nest pas explicitement dans un BEGIN
COMMIT, le moteur doit crer une image de certains
morceaux de la base en cours de modifcation afn de
grer son systme dannulation. SQLite a besoin de
256 octets de RAM pour chaque mgaoctet de base.
Pour de petites bases, ce cot mmoire nest pas un
problme ; mais lorsque la base de donnes atteint le
gigaoctet, la taille de cette image devient importante.
Si vous avez besoin de stocker et modifer plus de
quelques dizaines de mgaoctets, vous devriez envisa-
ger dutiliser un autre moteur de base de donnes.
Forte demande daccs simultans
SQLite utilise des verrous de lecture/criture sur
lensemble de la base. Cela signife que ds quun pro-
cessus lit une partie de la base, tous les autres sont
empchs dcrire dans nimporte quelle autre partie
de celle-ci (et inversement). Dans bien des cas, ce nest
pas forcment un problme (une opration dure rare-
ment plus de quelques dizaines de millisecondes).
Mais pour les applications devant grer beaucoup
daccs simultans, il faudra se tourner vers une autre
solution.
Las ou un auIrc moIcur csI p|us approprc
828 LhAPIJL 15 8asc dc donnccs
Crer et utiliser une base
avec linterprteur SQLite
sqlite3 nom_de_fchier // Unix/Linux/Mac OS X
sqlite3.exe nom_de_fchier // Windows
La bibliothque SQLite inclut un utilitaire en ligne de
commande appel sqlite3 (ou sqlite3.exe sous Windows)
pour saisir et excuter des requtes SQL sur une base de
donne SQLite. Pour lancer ce programme, il sufft de
taper sqlite3 (ou sqlite3.exe) suivi du nom de fchier
contenant la base de donnes. Si le fchier nexiste pas, ce
programme le crera automatiquement. Une invite de
commande apparat ensuite dans laquelle vous pourrez
saisir et excuter des requtes SQL.
Lexemple ci-aprs vous montre comment crer une base
nomme exemple1.db avec une seule table table1 conte-
nant quelques champs.
C:\Projet1\> sqlite3.exe exmple1.db
SQLite version 3.6.6
Enter .help for instructions
sqlite> create table table1(un varchar(10), deux smallint);
sqlite> insert into table1 values(bonjour!,10);
sqlite> insert into table1 values(au revoir,20);
sqlite> select * from table1;
bonjour!
|
10
au revoir
|
20
sqlite>
Pour quitter linterprteur sqlite3, appuyez sur les touches
Ctrl+D ou Ctrl+C. Vous pouvez aussi utiliser la com-
mande spciale .exit (attention au point au dbut de
celle-ci).
820
AIIcnIon
Prenez garde bien terminer chacune de vos requtes par un
point-virgule (;). Cest sa prsence qui permet linterprteur
sqlite3 de dterminer la fn dune requte. Si vous lomettez,
sqlite3 affchera une invite dite de continuation et attendra le
reste de la requte.
Lexemple suivant montre comment se passe une requte mul-
tiligne :
sqlite> create table table2 (
> f1 varchar(30) primary key,
> f2 text,
> f3 real
> );
sqlite>

Linterprteur sqlite3 possde galement quelques com-
mandes internes, qui commencent toutes par le signe point
(.) (les dot commands). Elles servent principalement modi-
fer le format daffchage du rsultat des requtes ou ex-
cuter certaines instructions de requtes prconditionnes.
Le tableau ci-dessous fournit un rcapitulatif de ces com-
mandes.
Commandes internes (interprteur sqlite3)
Lommandc 0cscrpIon
.help Affche la liste des commandes spciales
.bail ON
|
OFF Sarrter la premire erreur rencontre. OFF
par dfaut.
.databases Lister les noms et fchiers bases lies
.dump ?TABLE? ... Faire une image (dump) de la base sous forme
de requtes SQL dans un fchier texte
Lrccr cI uI|scr unc hasc avcc |nIcrprcIcur S0LIc
880 LhAPIJL 15 8asc dc donnccs
Commandes internes (interprteur sqlite3) (Suite)
Lommandc 0cscrpIon
.echo ON
|
OFF Activer ou dsactiver laffchage
.exit Quitter linterprteur
.explain ON
|
OFF Activer ou dsactiver le mode de sortie applicable
EXPLAIN
.header(s) ON
|
OFF Activer ou dsactiver laffchage des en-ttes
.help Affche la liste et la description des commandes
spciales
.import FILE TABLE Importer les donnes de FILE dans la TABLE
.indices TABLE Montrer le nom de tous les index de TABLE
.load FILE ?ENTRY? Charger une bibliothque dextensions
.mode MODE ?TABLE? Choisir le mode de sortie, o MODE est parmi la liste
suivante :
csv : donnes spares par des points-virgules
column : colonnes alignes gauche (voir aussi
.width)
html : sous forme de <table> HTML
insert : sous forme dinstruction dinsertion SQL
pour TABLE
line : une valeur par ligne
list : valeurs spares par la chane de sparation
.string
tabs : valeurs spares par des tabulations
tcl : sous forme dlments de liste TCL
.nullvalue STRING Affche STRING la place des valeurs nulles (vides)
NULL
.output FILENAME Envoyer la sortie vers le fchier FILENAME
.output stdout Envoyer la sortie vers lcran/console
.prompt MAIN
CONTINUE
Remplacer les invites (prompts) standard
881
Commandes internes (interprteur sqlite3) (Suite)
Lommandc 0cscrpIon
.quit Quitter linterprteur
.read FILENAME Excuter la requte SQL prsente dans le fchier
FILENAME
.schema ?TABLE? Affcher les instructions CREATE
.separator STRING Changer le sparateur utilis pour la sortie et
limport
.show Montrer la valeur courante des diffrentes options
.tables ?PATTERN? Lister les noms des tables correspondant un
modle LIKE
.timeout MS Essayer douvrir une table verrouille pendant MS
millisecondes
.width NUM NUM ... Spcifer la largeur des colonnes en mode colonne
Crer/ouvrir une base (SQLite)
int sqlite3_open(
const char *flename, /* Database flename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int sqlite3_open16(
const void *flename, /* Database flename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int sqlite3_open_v2(
const char *flename, /* Database flename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int fags, /* Flags */
const char *zVfs /* Name of VFS module to use */
);
Lrccrjouvrr unc hasc (S0LIc)
882 LhAPIJL 15 8asc dc donnccs
Ces routines permettent douvrir une base de donnes
SQLite dont le nom de fchier est donn en paramtre. Le
nom de fchier et lencodage par dfaut de la base sont
considrs comme tant de lUTF-8 pour sqlite3open() et
sqlite3_open_v2(), mais de lUTF-16 pour sqlite3_open16().
Un pointeur vers une instance de sqlite3 est renvoy par le
paramtre ppDb mme si une erreur apparat ( lexception
de limpossibilit dallouer la mmoire pour cette instance,
auquel cas un pointeur NULL est retourn).
Info
Si le nom de fchier est une chane vide ou :memory: alors
une base prive est cre en mmoire. Cette dernire dispara-
tra sa fermeture.
Si une base est ouverte (et/ou cre) avec succs, alors
SQLITE_OK est retourn par la fonction ; sinon un code
derreur est renvoy. Les fonctions sqlite3_errmsg() ou
sqlite3_errmsg16() permettent dobtenir un descriptif de
lerreur en anglais.
AIIcnIon
Selon le code derreur, il peut tre ncessaire de fermer correc-
tement la connexion avec sqlite3_close().
Le paramtre fags supplmentaire de sqlite3_open_v2()
permet de spcifer loption douverture de la base :
SQLITE_OPEN_READONLY. Ouvrir la base en lecture seule.
Si la base nexiste pas, une erreur est renvoye ;
SQLITE_OPEN_READWRITE. Ouvrir la base en lecture/cri-
ture. Si le fchier est en lecture seule, la base sera ouverte
en lecture seule. Dans les deux cas, le fchier doit exister
sinon une erreur est renvoye ;
888
SQLITE_OPEN_READWRITE
|
SQLITE_OPEN_CREATE. Ouvrir la
base en lecture/criture, et crer celle-ci sil nexiste
pas. Cest le comportement par dfaut des fonctions
sqlite3_open() et sqlite3_open16().
Il est possible de combiner ces trois modes douverture
avec lune des deux autres options suivantes :
SQLITE_OPEN_NOMUTEX. La base est ouverte avec le support
du multithread (du moins si loption de compilation
singlethread na pas t active ou que cette mme
option na pas t spcife) ;
SQLITE_OPEN_FULLMUTEX. La base est ouverte avec le sup-
port du multithread travers un mcanisme de sriali-
sation.
Le dernier paramtre zVfs de sqlite3_open_v2() permet
de dfnir linterface des oprations systme que la
connexion la base SQLite doit utiliser (reportez-vous au
manuel de SQLite pour plus dinformations).
Un exemple de mise en uvre de la fonction sqlite3_
open() est disponible la section Lancer une requte
avec SQLite .
Codes derreur des fonctions sqlite3_open*()
Lodc va|cur 0cscrpIon
SQLITE_OK 0 Pas derreur
SQLITE_ERROR 1 Erreur SQL ou base manquante
SQLITE_INTERNAL 2 Erreur logique interne SQLite
SQLITE_PERM 3 Permission daccs refuse
SQLITE_ABORT 4 Une fonction callback a demand
un abandon
Lrccrjouvrr unc hasc (S0LIc)
884 LhAPIJL 15 8asc dc donnccs
Lodc va|cur 0cscrpIon
SQLITE_BUSY 5 Le fchier de base de donnes est ver-
rouill
SQLITE_LOCKED 6 Une table de la base est verrouille
SQLITE_NOMEM 7 Un malloc() a chou
SQLITE_READONLY 8 Tentative dcriture sur une base en lec-
ture seule
SQLITE_INTERRUPT 9 Opration termine par sqlite3_inter-
rupt()
SQLITE_IOERR 10 Une erreur dE/S disque est survenue
SQLITE_CORRUPT 11 Limage de la base est corrompue
SQLITE_NOTFOUND 12 Non utilis. Table ou enregistrement non
trouv.
SQLITE_FULL 13 chec de linsertion car base pleine
SQLITE_CANTOPEN 14 Impossible douvrir le fchier de base de
donnes
SQLITE_PROTOCOL 15 Non utilis. Erreur du protocole de ver-
rouillage de la base.
SQLITE_EMPTY 16 Base de donnes vide
SQLITE_SCHEMA 17 Le schma de la base a chang
SQLITE_TOOBIG 18 La chane ou le BLOB dpasse la taille
maximale autorise
SQLITE_CONSTRAIN 19 Abandon d la violation dune
contrainte
SQLITE_MISMATCH 20 Type de donne inadapt
SQLITE_MISUSE 21 Bibliothque utilise incorrectement
Codes derreur des fonctions sqlite3_open*() (Suite)
885
Lodc va|cur 0cscrpIon
SQLITE_NOLFS 22 Utilisation de spcifcit systme non
supporte sur lhte
SQLITE_AUTH 23 Autorisation refuse
SQLITE_FORMAT 24 Erreur de format de la base auxiliaire
SQLITE_RANGE 25 2
e
paramtre de sqlite3_bind() hors
borne
SQLITE_NOTADB 26 Le fchier ouvrir nest pas une base de
donnes
SQLITE_ROW 100 sqlite3_step() a une autre ligne prte
SQLITE_DONE 101 sqlite3_step() a fni son excution
Lancer une requte avec SQLite
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**),
/* Callback */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
La fonction sqlite3_exec() permet dexcuter une ou
plusieurs instructions SQL sans avoir crire beaucoup de
code. Les instructions SQL (encodes en UTF-8) sont
passes en deuxime paramtre. Ces instructions sont ex-
cutes une une jusqu rencontrer une erreur, ou que
toutes soient excutes. Le troisime paramtre est un
Lanccr unc rcquIc avcc S0LIc
Codes derreur des fonctions sqlite3_open*() (Suite)
888 LhAPIJL 15 8asc dc donnccs
callback optionnel appel une fois pour chaque ligne pro-
duite par lexcution de toutes les instructions SQL four-
nies. Le cinquime paramtre prcise o crire un ventuel
message derreur.
AIIcnIon
Tout message derreur renvoy a t allou laide de la fonc-
tion sql3_malloc(). Pour viter des pertes mmoire, vous
devez imprativement librer cette mmoire avec sqlite3_
free().
Lexemple suivant illustre la manire de lire les donnes
dune base. Pour toute autre opration, il sufft de crer la
requte SQL ncessaire et de lexcuter.
#include <stdio.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv,

char **azColName)
{
int i;
for(i=0; i<argc; i++)
{
printf(%s = %s\n, azColName[i], argv[i] ?

argv[i] : NULL);
}
printf(\n);
return 0;
}

int main(int argc, char **argv)
{
sqlite3 *db;
char *zErrMsg = 0;
881
int rc;
if( argc!=3 )
{
fprintf(stderr, Usage: %s DATABASE

SQL-STATEMENT\n, argv[0]);
exit(1);
}
rc = sqlite3_open(argv[1], &db);
if( rc )
{
fprintf(stderr, Cant open database: %s\n,

sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
if( rc!=SQLITE_OK )
{
fprintf(stderr, SQL error: %s\n, zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
Exemple dutilisation de lAPI de SQLite
Fermer une base (SQLite)
int sqlite3_close(sqlite3 *);
Cette fonction est le destructeur dun objet sqlite3.
Fcrmcr unc hasc (S0LIc)
888 LhAPIJL 15 8asc dc donnccs
AIIcnIon
Votre application doit terminer toutes les instructions prpa-
res et fermer tous les pointeurs de BLOB associs avec lobjet
sqlite3 avant de le fermer. Si sqlite3_close() est invoque
alors quune transaction tait ouverte, celle-ci sera automati-
quement annule.
Un exemple de mise en uvre de la fonction sqlite3_
close() est disponible dans la section Lancer une requte
avec SQLite .
AsIucc
La fonction sqlite3_next_stmt() peut tre utilise pour
connatre toutes les instructions prpares associes une
connexion. Un exemple type pourrait tre :
sqlite3_stmt *pStmt;
while ( (pStmt=sqlite3_next_stmt(db,0)) != 0 )
{
Sqlite3_fnalize(pStmt);
}

Crer une table (requte SQL)
CREATE TABLE NomDeLaTable
(NomColonne1 Type,
NomColonne1 Type,
);
Cette requte permet de crer une nouvelle table dans la
base de donnes active. Le nom de la table est prciser
aprs CREATE TABLE. Si le moteur sous-jacent supporte les
880
espaces, il faut encadrer le nom par des guillemets doubles ().
Vient ensuite la description des colonnes entre parenthses.
Il est possible dattribuer des valeurs par dfaut chaque
colonne. Cette valeur est utile lorsquaucune valeur nest
spcife pour ladite colonne au moment dune insertion.
Pour spcifer une valeur par dfaut, il sufft dajouter
default V aprs la dfnition du type de donne, o V est la
valeur par dfaut souhaite.
CREATE TABLE client
(Nom char(50),
Prenom char(50),
Addresse char(50) default Inconnue,
Ville char(50) default Paris,
Pays char(25),
Date_de_naissance date)
Les tableaux suivants recensent les diffrents types de donnes
disponibles pour les bases SQLite, MySQL et Oracle.
Type SQLite
Jypc 0cscrpIon
NUMERIC Si la donne peut tre convertie en entier alors elle est stoc-
ke en tant que INTEGER, si elle peut tre convertie en rel
alors elle est stocke en tant que REAL, sinon elle est stocke
en tant que TEXT. Aucune conversion en BLOB (abrviation de
Binary Large Object) ou valeur vide (NULL) nest faite.
INTEGER La valeur est un entier stock sur 1 8 octets en fonction
de sa valeur
REAL La valeur est un rel, stock en reprsentation IEEE 8 octets
TEXT La valeur est un texte, stock dans lencodage de la base
(UTF-8, UTF-16-BE ou UTF-16-LE)
BLOB La valeur est un objet binaire BLOB stock exactement
comme fourni
Lrccr unc Iah|c (rcquIc S0L)
840 LhAPIJL 15 8asc dc donnccs
T
y
p
e

M
y
S
Q
L
J
y
p
c
J
a

|
|
c
0
c
s
c
r

p
I

o
n
T
I
N
Y
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
1

o
c
t
e
t
C
e

t
y
p
e

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

1
2
8


1
2
7

s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t

s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s

d
e

0


2
5
5

S
M
A
L
L
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
2

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

3
2

7
6
8


3
2

7
6
7

s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t

s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s

d
e

0


6
5

5
3
5

M
E
D
I
U
M
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
3

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

8

3
8
8

6
0
8


8

3
8
8

6
0
7


s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t

s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s


d
e

0


1
6

7
7
7

2
1
5
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
4

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

2

1
4
7

4
8
3

6
4
8


2

1
4
7

4
8
3

6
4
7

s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t


s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s

d
e

0


4

2
9
4

9
6
7

2
9
5
I
N
T
E
G
E
R

[
M
]

[
U
N
S
I
G
N
E
D
]
.
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

I
N
T
B
I
G
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
8

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

s
t
o
c
k
e

l
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

a
l
l
a
n
t

d
e

9

2
2
3

3
7
2

0
3
6

8
5
4

7
7
5

8
0
8



9

2
2
3

3
7
2

0
3
6

8
5
4

7
7
5

8
0
7

s
a
n
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

e
t

d
e

0


1
8

4
4
6

7
4
4

0
7
3

7
0
9

5
5
1

6
1
5

a
v
e
c
F
L
O
A
T

[
U
N
S
I
G
N
E
D
]
4

o
u

8

o
c
t
e
t
s
S
t
o
c
k
e

u
n

n
o
m
b
r
e

d
e

t
y
p
e

f
o
t
t
a
n
t
,

e
n

p
r

c
i
s
i
o
n

s
i
m
p
l
e

d
e

0


2
4

o
u

p
r

c
i
s
i
o
n

d
o
u
b
l
e


d
e

2
5


5
3

(
o
c
c
u
p
e

4

o
c
t
e
t
s

s
i

l
a

p
r

c
i
s
i
o
n

e
s
t

i
n
f

r
i
e
u
r
e


2
4

o
u

8

a
u
-
d
e
l

)
F
L
O
A
T
[
(
M
,
D
)
]

[
U
N
S
I
G
N
E
D
]
4

o
c
t
e
t
s
M

e
s
t

l
e

n
o
m
b
r
e

d
e

c
h
i
f
f
r
e
s

e
t

D

e
s
t

l
e

n
o
m
b
r
e

d
e

d

c
i
m
a
l
e
s
.

C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
r
m
e
t

d
e

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

f
o
t
t
a
n
t
s


p
r

c
i
s
i
o
n

s
i
m
p
l
e
.

V
a

d
e

1
,
1
7
5
4
9
4
3
5
1
E
-
3
8


3
,
4
0
2
8
2
3
4
6
6
E
+
3
8
.

S
i

U
N
S
I
G
N
E
D

e
s
t

a
c
t
i
v

,

l
e
s

n
o
m
b
r
e
s

n

g
a
t
i
f
s


s
o
n
t

r
e
t
i
r

s

m
a
i
s

c
e
l
a

n
e

p
e
r
m
e
t

p
a
s

d

a
v
o
i
r

d
e
s

n
o
m
b
r
e
s

p
o
s
i
t
i
f
s

p
l
u
s

g
r
a
n
d
s
.
D
O
U
B
L
E

P
R
E
C
I
S
I
O
N
[
(
M
,
D
)
]
8

o
c
t
e
t
s
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

D
O
U
B
L
E
D
O
U
B
L
E

[
(
M
,
D
)
]
8

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

n
o
m
b
r
e
s

f
o
t
t
a
n
t
s


d
o
u
b
l
e

p
r

c
i
s
i
o
n

d
e

1
,
7
9
7
6
9
3
1
3
4
8
6
2
3
1
5
7
E
+
3
0
8


1
,
7
9
7
6
9
3
1
3
4
8
6
2
3
1
5
7
E
+
3
0
8

(
j
u
s
q
u

2
,
2
2
5
0
7
3
8
5
8
5
0
7
2
0
1
4
E

3
0
8

e
n

s
e

r
a
p
p
r
o
c
h
a
n
t


d
e

0
)
.

S
i

U
N
S
I
G
N
E
D

e
s
t

a
c
t
i
v

,

l
e
s

n
o
m
b
r
e
s

n

g
a
t
i
f
s

s
o
n
t

r
e
t
i
r

s

m
a
i
s

c
e
l
a

n
e

p
e
r
m
e
t

p
a
s

d

a
v
o
i
r

d
e
s

n
o
m
b
r
e
s

p
o
s
i
t
i
f
s

p
l
u
s

g
r
a
n
d
s
.
R
E
A
L
[
(
M
,
D
)
]
8

o
c
t
e
t
s
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

D
O
U
B
L
E
D
E
C
I
M
A
L
[
(
M
[
,
D
]
)
]
M
+
2

o
c
t
e
t
s

s
i

D

>

0
,

M
+
1

o
c
t
e
t
s

s
i

D

=

0
C
o
n
t
i
e
n
t

d
e
s

n
o
m
b
r
e
s

f
o
t
t
a
n
t
s

s
t
o
c
k

s

c
o
m
m
e

d
e
s

c
h
a

n
e
s

d
e

c
a
r
a
c
t

r
e
s
N
U
M
E
R
I
C

[
(
M
,
D
)
]
.
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

D
E
C
I
M
A
L
D
A
T
E
3

o
c
t
e
t
s
S
t
o
c
k
e

u
n
e

d
a
t
e

a
u

f
o
r
m
a
t

A
A
A
A
-
M
M
-
J
J


a
l
l
a
n
t

d
e

1
0
0
0
-
0
1
-
0
1

9
9
9
9
-
1
2
-
3
1

841
T
y
p
e

M
y
S
Q
L
J
y
p
c
J
a

|
|
c
0
c
s
c
r

p
I

o
n
T
I
N
Y
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
1

o
c
t
e
t
C
e

t
y
p
e

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

1
2
8


1
2
7

s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t

s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s

d
e

0


2
5
5

S
M
A
L
L
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
2

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

3
2

7
6
8


3
2

7
6
7

s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t

s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s

d
e

0


6
5

5
3
5

M
E
D
I
U
M
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
3

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

8

3
8
8

6
0
8


8

3
8
8

6
0
7


s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t

s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s


d
e

0


1
6

7
7
7

2
1
5
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
4

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
u
t

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

d
e

2

1
4
7

4
8
3

6
4
8


2

1
4
7

4
8
3

6
4
7

s

i
l

n
e

p
o
r
t
e

p
a
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

d
a
n
s

l
e

c
a
s

c
o
n
t
r
a
i
r
e

i
l

p
e
u
t


s
t
o
c
k
e
r

d
e
s

e
n
t
i
e
r
s

d
e

0


4

2
9
4

9
6
7

2
9
5
I
N
T
E
G
E
R

[
M
]

[
U
N
S
I
G
N
E
D
]
.
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

I
N
T
B
I
G
I
N
T

[
M
]

[
U
N
S
I
G
N
E
D
]
8

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

s
t
o
c
k
e

l
e
s

n
o
m
b
r
e
s

e
n
t
i
e
r
s

a
l
l
a
n
t

d
e

9

2
2
3

3
7
2

0
3
6

8
5
4

7
7
5

8
0
8



9

2
2
3

3
7
2

0
3
6

8
5
4

7
7
5

8
0
7

s
a
n
s

l

a
t
t
r
i
b
u
t

U
N
S
I
G
N
E
D
,

e
t

d
e

0


1
8

4
4
6

7
4
4

0
7
3

7
0
9

5
5
1

6
1
5

a
v
e
c
F
L
O
A
T

[
U
N
S
I
G
N
E
D
]
4

o
u

8

o
c
t
e
t
s
S
t
o
c
k
e

u
n

n
o
m
b
r
e

d
e

t
y
p
e

f
o
t
t
a
n
t
,

e
n

p
r

c
i
s
i
o
n

s
i
m
p
l
e

d
e

0


2
4

o
u

p
r

c
i
s
i
o
n

d
o
u
b
l
e


d
e

2
5


5
3

(
o
c
c
u
p
e

4

o
c
t
e
t
s

s
i

l
a

p
r

c
i
s
i
o
n

e
s
t

i
n
f

r
i
e
u
r
e


2
4

o
u

8

a
u
-
d
e
l

)
F
L
O
A
T
[
(
M
,
D
)
]

[
U
N
S
I
G
N
E
D
]
4

o
c
t
e
t
s
M

e
s
t

l
e

n
o
m
b
r
e

d
e

c
h
i
f
f
r
e
s

e
t

D

e
s
t

l
e

n
o
m
b
r
e

d
e

d

c
i
m
a
l
e
s
.

C
e

t
y
p
e

d
e

d
o
n
n

e
s

p
e
r
m
e
t

d
e

s
t
o
c
k
e
r

d
e
s

n
o
m
b
r
e
s

f
o
t
t
a
n
t
s


p
r

c
i
s
i
o
n

s
i
m
p
l
e
.

V
a

d
e

1
,
1
7
5
4
9
4
3
5
1
E
-
3
8


3
,
4
0
2
8
2
3
4
6
6
E
+
3
8
.

S
i

U
N
S
I
G
N
E
D

e
s
t

a
c
t
i
v

,

l
e
s

n
o
m
b
r
e
s

n

g
a
t
i
f
s


s
o
n
t

r
e
t
i
r

s

m
a
i
s

c
e
l
a

n
e

p
e
r
m
e
t

p
a
s

d

a
v
o
i
r

d
e
s

n
o
m
b
r
e
s

p
o
s
i
t
i
f
s

p
l
u
s

g
r
a
n
d
s
.
D
O
U
B
L
E

P
R
E
C
I
S
I
O
N
[
(
M
,
D
)
]
8

o
c
t
e
t
s
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

D
O
U
B
L
E
D
O
U
B
L
E

[
(
M
,
D
)
]
8

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

n
o
m
b
r
e
s

f
o
t
t
a
n
t
s


d
o
u
b
l
e

p
r

c
i
s
i
o
n

d
e

1
,
7
9
7
6
9
3
1
3
4
8
6
2
3
1
5
7
E
+
3
0
8


1
,
7
9
7
6
9
3
1
3
4
8
6
2
3
1
5
7
E
+
3
0
8

(
j
u
s
q
u

2
,
2
2
5
0
7
3
8
5
8
5
0
7
2
0
1
4
E

3
0
8

e
n

s
e

r
a
p
p
r
o
c
h
a
n
t


d
e

0
)
.

S
i

U
N
S
I
G
N
E
D

e
s
t

a
c
t
i
v

,

l
e
s

n
o
m
b
r
e
s

n

g
a
t
i
f
s

s
o
n
t

r
e
t
i
r

s

m
a
i
s

c
e
l
a

n
e

p
e
r
m
e
t

p
a
s

d

a
v
o
i
r

d
e
s

n
o
m
b
r
e
s

p
o
s
i
t
i
f
s

p
l
u
s

g
r
a
n
d
s
.
R
E
A
L
[
(
M
,
D
)
]
8

o
c
t
e
t
s
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

D
O
U
B
L
E
D
E
C
I
M
A
L
[
(
M
[
,
D
]
)
]
M
+
2

o
c
t
e
t
s

s
i

D

>

0
,

M
+
1

o
c
t
e
t
s

s
i

D

=

0
C
o
n
t
i
e
n
t

d
e
s

n
o
m
b
r
e
s

f
o
t
t
a
n
t
s

s
t
o
c
k

s

c
o
m
m
e

d
e
s

c
h
a

n
e
s

d
e

c
a
r
a
c
t

r
e
s
N
U
M
E
R
I
C

[
(
M
,
D
)
]
.
M

m
e

c
h
o
s
e

q
u
e

l
e

t
y
p
e

D
E
C
I
M
A
L
D
A
T
E
3

o
c
t
e
t
s
S
t
o
c
k
e

u
n
e

d
a
t
e

a
u

f
o
r
m
a
t

A
A
A
A
-
M
M
-
J
J


a
l
l
a
n
t

d
e

1
0
0
0
-
0
1
-
0
1

9
9
9
9
-
1
2
-
3
1

Lrccr unc Iah|c (rcquIc S0L)


842 LhAPIJL 15 8asc dc donnccs
J
y
p
c
J
a

|
|
c
0
c
s
c
r

p
I

o
n
D
A
T
E
T
I
M
E
8

o
c
t
e
t
s
S
t
o
c
k
e

u
n
e

d
a
t
e

e
t

u
n
e

h
e
u
r
e

a
u

f
o
r
m
a
t

A
A
A
A
-
M
M
-
J
J

H
H
:
M
M
:
S
S


a
l
l
a
n
t


d
e

1
0
0
0
-
0
1
-
0
1

0
0
:
0
0
:
0
0

9
9
9
9
-
1
2
-
3
1

2
3
:
5
9
:
5
9

T
I
M
E
S
T
A
M
P

[
M
]
4

o
c
t
e
t
s
S
t
o
c
k
e

u
n
e

d
a
t
e

s
o
u
s

f
o
r
m
e

n
u
m

r
i
q
u
e

a
l
l
a
n
t

d
e

1
9
7
0
-
0
1
-
0
1

0
0
:
0
0
:
0
0

a
n
n

e

2
0
3
7
.

L

a
f
f
c
h
a
g
e

d

p
e
n
d

d
e
s

v
a
l
e
u
r
s

d
e

M

:

A
A
A
A
M
M
J
J
H
H
M
M
S
S
,

A
A
M
M
J
J
H
H
M
M
S
S
,

A
A
A
A
M
M
J
J
,

o
u

A
A
M
M
J
J

p
o
u
r

M

g
a
l

r
e
s
p
e
c
t
i
v
e
m
e
n
t


1
4
,

1
2
,

8
,

e
t

6
.
T
I
M
E
3

o
c
t
e
t
s
S
t
o
c
k
e

l

h
e
u
r
e

a
u

f
o
r
m
a
t

H
H
:
M
M
:
S
S

,

a
l
l
a
n
t

d
e

-
8
3
8
:
5
9
:
5
9

8
3
8
:
5
9
:
5
9

Y
E
A
R
1

o
c
t
e
t
A
n
n


2

o
u

4

c
h
i
f
f
r
e
s

a
l
l
a
n
t

d
e

1
9
0
1


2
1
5
5

(
4

c
h
i
f
f
r
e
s
)

e
t

d
e

1
9
7
0
-
2
0
6
9

(
2

c
h
i
f
f
r
e
s
)
[
N
A
T
I
O
N
A
L
]


C
H
A
R
(
M
)

[
B
I
N
A
R
Y
]
M

o
c
t
e
t
s
C
h
a

n
e

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m

r
e
m
p
l
i
e

d

e
s
p
a
c
e
s


l
a

f
n
.

L

o
p
t
i
o
n

B
I
N
A
R
Y


e
s
t

u
t
i
l
i
s

e

p
o
u
r

t
e
n
i
r

c
o
m
p
t
e

d
e

l
a

c
a
s
s
e
.
B
I
T
1

o
c
t
e
t
M

m
e

c
h
o
s
e

q
u
e

C
H
A
R
(
1
)
B
O
O
L
1

o
c
t
e
t
M

m
e

c
h
o
s
e

q
u
e

C
H
A
R
(
1
)
C
H
A
R

(
M
)
M

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
a
r
a
c
t

r
e
s
.

S
i

v
o
u
s

s
t
o
c
k
e
z

u
n

c
a
r
a
c
t

r
e

e
t

q
u
e

M

v
a
u
t

2
5
5
,

l
a

d
o
n
n

e

p
r
e
n
d
r
a

2
5
5

o
c
t
e
t
s
.

A
u
t
a
n
t

d
o
n
c

e
m
p
l
o
y
e
r

c
e

t
y
p
e

d
e

d
o
n
n

e
s

p
o
u
r

d
e
s

m
o
t
s

d
e

l
o
n
g
u
e
u
r

i
d
e
n
t
i
q
u
e
.
V
A
R
C
H
A
R

(
M
)

[
B
I
N
A
R
Y
]
L
+
1

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

s
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

L

o
p
t
i
o
n

B
I
N
A
R
Y

p
e
r
m
e
t

d
e

t
e
n
i
r

c
o
m
p
t
e

d
e

l
a

c
a
s
s
e

(
L

r
e
p
r

s
e
n
t
e

l
a

l
o
n
g
u
e
u
r

d
e

l
a

c
h
a

n
e
)
.
T
I
N
Y
B
L
O
B
L
+
1

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

s
e
n
s
i
b
l
e


l
a

c
a
s
s
e


(
L

r
e
p
r

s
e
n
t
e

l
a

l
o
n
g
u
e
u
r

d
e

l
a

c
h
a

n
e
)
.
T
I
N
Y
T
E
X
T
L
+
1

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

i
n
s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
B
L
O
B
L
+
1

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

C
h
a

n
e
s

d
e

6
5

5
3
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
T
E
X
T
L
+
2

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

6
5

5
3
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

i
n
s
e
n
s
i
b
l
e


l
a

c
a
s
s
e


(
L

r
e
p
r

s
e
n
t
e

l
a

l
o
n
g
u
e
u
r

d
e

l
a

c
h
a

n
e
)
.
M
E
D
I
U
M
B
L
O
B
L
+
3

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

1
6

7
7
7

2
1
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.
M
E
D
I
U
M
T
E
X
T
L
+
3

o
c
t
e
t
s
C
h
a

n
e

d
e

1
6

7
7
7

2
1
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

i
n
s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
L
O
N
G
B
L
O
B
L
+
4

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

4

2
9
4

9
6
7

2
9
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
L
O
N
G
T
E
X
T
L
+
4

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

4

2
9
4

9
6
7

2
9
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.
E
N
U
M
(

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
1

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
2

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
3

,
.
.
.
)
1

o
u

2

o
c
t
e
t
s

(
l
a

p
l
a
c
e

o
c
c
u
p

e

e
s
t

f
o
n
c
t
i
o
n

d
u

n
o
m
b
r
e

d
e

s
o
l
u
t
i
o
n
s

p
o
s
s
i
b
l
e
s

:

6
5

5
3
5

v
a
l
e
u
r
s

m
a
x
i
m
u
m
.
S
E
T
(

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
1

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
2

,
.
.
.
)
1
,

2
,

3
,

4

o
u

8

o
c
t
e
t
s

s
e
l
o
n

d
e

n
o
m
b
r
e

d
e

s
o
l
u
t
i
o
n
s

p
o
s
s
i
b
l
e
s

(
d
e

0


6
4

v
a
l
e
u
r
s

m
a
x
i
m
u
m
)
.
848
J
y
p
c
J
a

|
|
c
0
c
s
c
r

p
I

o
n
D
A
T
E
T
I
M
E
8

o
c
t
e
t
s
S
t
o
c
k
e

u
n
e

d
a
t
e

e
t

u
n
e

h
e
u
r
e

a
u

f
o
r
m
a
t

A
A
A
A
-
M
M
-
J
J

H
H
:
M
M
:
S
S


a
l
l
a
n
t


d
e

1
0
0
0
-
0
1
-
0
1

0
0
:
0
0
:
0
0

9
9
9
9
-
1
2
-
3
1

2
3
:
5
9
:
5
9

T
I
M
E
S
T
A
M
P

[
M
]
4

o
c
t
e
t
s
S
t
o
c
k
e

u
n
e

d
a
t
e

s
o
u
s

f
o
r
m
e

n
u
m

r
i
q
u
e

a
l
l
a
n
t

d
e

1
9
7
0
-
0
1
-
0
1

0
0
:
0
0
:
0
0

a
n
n

e

2
0
3
7
.

L

a
f
f
c
h
a
g
e

d

p
e
n
d

d
e
s

v
a
l
e
u
r
s

d
e

M

:

A
A
A
A
M
M
J
J
H
H
M
M
S
S
,

A
A
M
M
J
J
H
H
M
M
S
S
,

A
A
A
A
M
M
J
J
,

o
u

A
A
M
M
J
J

p
o
u
r

M

g
a
l

r
e
s
p
e
c
t
i
v
e
m
e
n
t


1
4
,

1
2
,

8
,

e
t

6
.
T
I
M
E
3

o
c
t
e
t
s
S
t
o
c
k
e

l

h
e
u
r
e

a
u

f
o
r
m
a
t

H
H
:
M
M
:
S
S

,

a
l
l
a
n
t

d
e

-
8
3
8
:
5
9
:
5
9

8
3
8
:
5
9
:
5
9

Y
E
A
R
1

o
c
t
e
t
A
n
n


2

o
u

4

c
h
i
f
f
r
e
s

a
l
l
a
n
t

d
e

1
9
0
1


2
1
5
5

(
4

c
h
i
f
f
r
e
s
)

e
t

d
e

1
9
7
0
-
2
0
6
9

(
2

c
h
i
f
f
r
e
s
)
[
N
A
T
I
O
N
A
L
]


C
H
A
R
(
M
)

[
B
I
N
A
R
Y
]
M

o
c
t
e
t
s
C
h
a

n
e

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m

r
e
m
p
l
i
e

d

e
s
p
a
c
e
s


l
a

f
n
.

L

o
p
t
i
o
n

B
I
N
A
R
Y


e
s
t

u
t
i
l
i
s

e

p
o
u
r

t
e
n
i
r

c
o
m
p
t
e

d
e

l
a

c
a
s
s
e
.
B
I
T
1

o
c
t
e
t
M

m
e

c
h
o
s
e

q
u
e

C
H
A
R
(
1
)
B
O
O
L
1

o
c
t
e
t
M

m
e

c
h
o
s
e

q
u
e

C
H
A
R
(
1
)
C
H
A
R

(
M
)
M

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
a
r
a
c
t

r
e
s
.

S
i

v
o
u
s

s
t
o
c
k
e
z

u
n

c
a
r
a
c
t

r
e

e
t

q
u
e

M

v
a
u
t

2
5
5
,

l
a

d
o
n
n

e

p
r
e
n
d
r
a

2
5
5

o
c
t
e
t
s
.

A
u
t
a
n
t

d
o
n
c

e
m
p
l
o
y
e
r

c
e

t
y
p
e

d
e

d
o
n
n

e
s

p
o
u
r

d
e
s

m
o
t
s

d
e

l
o
n
g
u
e
u
r

i
d
e
n
t
i
q
u
e
.
V
A
R
C
H
A
R

(
M
)

[
B
I
N
A
R
Y
]
L
+
1

o
c
t
e
t
s
C
e

t
y
p
e

d
e

d
o
n
n

e
s

s
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

L

o
p
t
i
o
n

B
I
N
A
R
Y

p
e
r
m
e
t

d
e

t
e
n
i
r

c
o
m
p
t
e

d
e

l
a

c
a
s
s
e

(
L

r
e
p
r

s
e
n
t
e

l
a

l
o
n
g
u
e
u
r

d
e

l
a

c
h
a

n
e
)
.
T
I
N
Y
B
L
O
B
L
+
1

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

s
e
n
s
i
b
l
e


l
a

c
a
s
s
e


(
L

r
e
p
r

s
e
n
t
e

l
a

l
o
n
g
u
e
u
r

d
e

l
a

c
h
a

n
e
)
.
T
I
N
Y
T
E
X
T
L
+
1

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

2
5
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

i
n
s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
B
L
O
B
L
+
1

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

C
h
a

n
e
s

d
e

6
5

5
3
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
T
E
X
T
L
+
2

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

6
5

5
3
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

i
n
s
e
n
s
i
b
l
e


l
a

c
a
s
s
e


(
L

r
e
p
r

s
e
n
t
e

l
a

l
o
n
g
u
e
u
r

d
e

l
a

c
h
a

n
e
)
.
M
E
D
I
U
M
B
L
O
B
L
+
3

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

1
6

7
7
7

2
1
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.
M
E
D
I
U
M
T
E
X
T
L
+
3

o
c
t
e
t
s
C
h
a

n
e

d
e

1
6

7
7
7

2
1
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

i
n
s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
L
O
N
G
B
L
O
B
L
+
4

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

4

2
9
4

9
6
7

2
9
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.

C
e

c
h
a
m
p

e
s
t

s
e
n
s
i
b
l
e


l
a

c
a
s
s
e
.
L
O
N
G
T
E
X
T
L
+
4

o
c
t
e
t
s
S
t
o
c
k
e

d
e
s

c
h
a

n
e
s

d
e

4

2
9
4

9
6
7

2
9
5

c
a
r
a
c
t

r
e
s

m
a
x
i
m
u
m
.
E
N
U
M
(

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
1

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
2

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
3

,
.
.
.
)
1

o
u

2

o
c
t
e
t
s

(
l
a

p
l
a
c
e

o
c
c
u
p

e

e
s
t

f
o
n
c
t
i
o
n

d
u

n
o
m
b
r
e

d
e

s
o
l
u
t
i
o
n
s

p
o
s
s
i
b
l
e
s

:

6
5

5
3
5

v
a
l
e
u
r
s

m
a
x
i
m
u
m
.
S
E
T
(

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
1

v
a
l
e
u
r
_
p
o
s
s
i
b
l
e
2

,
.
.
.
)
1
,

2
,

3
,

4

o
u

8

o
c
t
e
t
s

s
e
l
o
n

d
e

n
o
m
b
r
e

d
e

s
o
l
u
t
i
o
n
s

p
o
s
s
i
b
l
e
s

(
d
e

0


6
4

v
a
l
e
u
r
s

m
a
x
i
m
u
m
)
.
Lrccr unc Iah|c (rcquIc S0L)
844 LhAPIJL 15 8asc dc donnccs
T
y
p
e
s

d
e

d
o
n
n

e
s

i
n
t
e
r
n
e
s

(
b
u
i
l
t
-
i
n
)

d

O
r
a
c
l
e
L
o
d
c

n
I
c
r
n
c

J
y
p
c
0
c
s
c
r

p
I

o
n
M

m
u
m
M
a
x

m
u
m
L
x
c
m
p
|
c
s

d
c

v
a
|
c
u
r
s
V
A
R
C
H
A
R
2

(
t
a
i
l
l
e
)
N
V
A
R
C
H
A
R
2

(
t
a
i
l
l
e
)
C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

v
a
r
i
a
b
l
e
C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

v
a
r
i
a
b
l
e


u
t
i
l
i
s
a
n
t

l
e

j
e
u

d
e

c
a
r
.

n
a
t
i
o
n
a
l
1

c
a
r
.
2
0
0
0

c
a
r
.

B
o
n
j
o
u
r

D
D

N
U
M
B
E
R


[
(
t
a
i
l
l
e
[
,
p
r
e
c
i
s
i
o
n
]
)
]
N
u
m

r
i
q
u
e

(
p
r
e
c
<
=
3
8
,

e
x
p
o
s
a
n
t


m
a
x

-
8
4

+
1
2
7
)
1
0
-
8
4
1
0
1
2
7
1
0
.
9
9
9
9

L
O
N
G

(
t
a
i
l
l
e
)

C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

v
a
r
i
a
b
l
e

1

c
a
r
.
2

g
i
g
a

c
a
r
.

A
A
A
H
H
H
H
H
H
.
.
.
H
H
H


D
A
T
E

D
a
t
e

(
d
u

s
i

c
l
e


l
a

s
e
c
o
n
d
e
)
0
1
/
0
1
/
-
4
7
1
2

(
a
v
a
n
t

J
.
-
C
.
)
3
1
/
1
2
/
9
9
9
9

1
0
-
F
E
B
-
0
4

1
0
/
0
2
/
0
4


(
d

p
e
n
d

d
u

f
o
r
m
a
t

d

a
f
f
c
h
a
g
e

o
u

d
u

p
a
r
a
m

t
r
a
g
e

l
o
c
a
l
)
R
A
W

(
t
a
i
l
l
e
)

D
o
n
n

e
s

b
i
n
a
i
r
e
s

d
e
v
a
n
t

t
r
e

e
n
t
r

e
s

e
n

n
o
t
a
t
i
o
n

h
e
x
a
d

c
i
m
a
l
e
.

T
a
i
l
l
e

:

1


2
5
5

c
a
r
a
c
t

r
e
s
1

o
c
t
e
t

2

0
0
0

o
c
t
e
t
s
L
O
N
G

R
A
W

(
t
a
i
l
l
e
)
D
o
n
n

e
s

b
i
n
a
i
r
e
s

d
e
v
a
n
t

t
r
e

e
n
t
r

e
s

e
n

n
o
t
a
t
i
o
n

h
e
x
a
d

c
i
m
a
l
e
1

o
c
t
e
t

2

G
o
R
O
W
I
D

T
y
p
e

r

s
e
r
v


l
a

p
s
e
u
d
o
-
c
o
l
o
n
n
e

R
O
W
I
D
.

N
e

p
e
u
t

t
r
e

u
t
i
l
i
s

.
C
H
A
R

(
t
a
i
l
l
e
)
N
C
H
A
R

(
t
a
i
l
l
e
)

C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

f
x
e
C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

f
x
e

u
t
i
l
i
s
a
n
t

l
e

j
e
u

d
e

c
a
r
.

n
a
t
i
o
n
a
l
1

c
a
r
.
2
5
5

c
a
r
.

A
Z
E
R
T
Y

C
L
O
C
N
C
L
O
B
L
O
B

d
e

t
y
p
e

c
a
r
a
c
t

r
e

m
o
n
o
-
o
c
t
e
t

o
u

m
u
l
t
i
-
o
c
t
e
t

u
t
i
l
i
s
a
n
t

l
e

j
e
u

d
e

c
a
r
.

n
a
t
i
o
n
a
l
1

o
c
t
e
t

4

g
i
g
a

c
a
r
.
B
L
O
B
B
L
O
B

!

g
r
o
s

o
b
j
e
t

b
i
n
a
i
r
e
1

o
c
t
e
t
4

g
i
g
a
-
o
c
t
e
t
s
B
F
I
L
E

P
o
i
n
t
e
u
r

v
e
r
s

u
n

f
c
h
i
e
r

b
i
n
a
i
r
e

e
x
t
e
r
n
e

1

o
c
t
e
t
4

g
i
g
a
-
o
c
t
e
t
s
T
I
M
E
S
T
A
M
P

(
f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n
)

D
a
t
e

(
a
n
n

e
,

m
o
i
s
,

e
t

j
o
u
r

p
l
u
s

h
e
u
r
e
,

m
i
n
u
t
e
,

s
e
c
o
n
d
e
s

e
t

q
u
a
n
t
i
t


d
e

f
r
a
c
t
i
o
n

d
e

s
e
c
o
n
d
e
)
,

o


f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n

e
s
t

l
e

n
o
m
b
r
e

d
e

c
h
i
f
f
r
e
s

d
e

l
a

p
a
r
t
i
e

f
r
a
c
t
i
o
n
n
a
i
r
e

d
e
s

s
e
c
o
n
d
e
s
.

L
e
s

v
a
l
e
u
r
s

v
o
n
t

d
e


0


9

(
1

p
o
u
r

l
e

d
i
x
i

m
e
,

2

p
o
u
r

l
e

c
e
n
t
i

m
e
,

)
.


L
a

v
a
l
e
u
r

p
a
r

d

f
a
u
t

e
s
t

6

(
l
e

m
i
l
l
i
o
n
i

m
e
)
.
T
I
M
E
S
T
A
M
P

(
f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n
)

W
I
T
H

L
O
C
A
L

T
I
M
E

Z
O
N
E
A
V
E
C

F
U
S
E
A
U

H
O
R
A
I
R
E

L
O
C
A
L

(
L
O
C
A
L

T
I
M
E

Z
O
N
E
)

T
o
u
t
e
s

l
e
s

v
a
l
e
u
r
s

d
o
n
n

e
s

d
a
n
s

l
e

f
u
s
e
a
u

h
o
r
a
i
r
e

l
o
c
a
l
,

a
v
e
c

l

e
x
c
e
p
t
i
o
n

s
u
i
v
a
n
t
e

:

l
e
s

d
o
n
n

e
s

s
o
n
t

n
o
r
m
a
l
i
s

e
s

d
a
n
s

l
e

f
u
s
e
a
u

d
e

l
a

b
a
s
e

l
o
r
s
q
u

e
l
l
e
s

y

s
o
n
t

s
t
o
c
-
k

e
s
.

L
o
r
s
q
u
e

l
e
s

d
o
n
n

e
s

s
o
n
t

r
e
l
u
e
s
,

e
l
l
e
s

s
o
n
t

c
o
n
v
e
r
t
i
e
s

d
a
n
s

l
e

f
u
s
e
a
u

h
o
r
a
i
r
e

l
o
c
a
l
.
845
T
y
p
e
s

d
e

d
o
n
n

e
s

i
n
t
e
r
n
e
s

(
b
u
i
l
t
-
i
n
)

d

O
r
a
c
l
e
L
o
d
c

n
I
c
r
n
c

J
y
p
c
0
c
s
c
r

p
I

o
n
M

m
u
m
M
a
x

m
u
m
L
x
c
m
p
|
c
s

d
c

v
a
|
c
u
r
s
V
A
R
C
H
A
R
2

(
t
a
i
l
l
e
)
N
V
A
R
C
H
A
R
2

(
t
a
i
l
l
e
)
C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

v
a
r
i
a
b
l
e
C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

v
a
r
i
a
b
l
e


u
t
i
l
i
s
a
n
t

l
e

j
e
u

d
e

c
a
r
.

n
a
t
i
o
n
a
l
1

c
a
r
.
2
0
0
0

c
a
r
.

B
o
n
j
o
u
r

D
D

N
U
M
B
E
R


[
(
t
a
i
l
l
e
[
,
p
r
e
c
i
s
i
o
n
]
)
]
N
u
m

r
i
q
u
e

(
p
r
e
c
<
=
3
8
,

e
x
p
o
s
a
n
t


m
a
x

-
8
4

+
1
2
7
)
1
0
-
8
4
1
0
1
2
7
1
0
.
9
9
9
9

L
O
N
G

(
t
a
i
l
l
e
)

C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

v
a
r
i
a
b
l
e

1

c
a
r
.
2

g
i
g
a

c
a
r
.

A
A
A
H
H
H
H
H
H
.
.
.
H
H
H


D
A
T
E

D
a
t
e

(
d
u

s
i

c
l
e


l
a

s
e
c
o
n
d
e
)
0
1
/
0
1
/
-
4
7
1
2

(
a
v
a
n
t

J
.
-
C
.
)
3
1
/
1
2
/
9
9
9
9

1
0
-
F
E
B
-
0
4

1
0
/
0
2
/
0
4


(
d

p
e
n
d

d
u

f
o
r
m
a
t

d

a
f
f
c
h
a
g
e

o
u

d
u

p
a
r
a
m

t
r
a
g
e

l
o
c
a
l
)
R
A
W

(
t
a
i
l
l
e
)

D
o
n
n

e
s

b
i
n
a
i
r
e
s

d
e
v
a
n
t

t
r
e

e
n
t
r

e
s

e
n

n
o
t
a
t
i
o
n

h
e
x
a
d

c
i
m
a
l
e
.

T
a
i
l
l
e

:

1


2
5
5

c
a
r
a
c
t

r
e
s
1

o
c
t
e
t

2

0
0
0

o
c
t
e
t
s
L
O
N
G

R
A
W

(
t
a
i
l
l
e
)
D
o
n
n

e
s

b
i
n
a
i
r
e
s

d
e
v
a
n
t

t
r
e

e
n
t
r

e
s

e
n

n
o
t
a
t
i
o
n

h
e
x
a
d

c
i
m
a
l
e
1

o
c
t
e
t

2

G
o
R
O
W
I
D

T
y
p
e

r

s
e
r
v


l
a

p
s
e
u
d
o
-
c
o
l
o
n
n
e

R
O
W
I
D
.

N
e

p
e
u
t

t
r
e

u
t
i
l
i
s

.
C
H
A
R

(
t
a
i
l
l
e
)
N
C
H
A
R

(
t
a
i
l
l
e
)

C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

f
x
e
C
h
a

n
e

d
e

c
a
r
a
c
t

r
e
s

d
e

l
o
n
g
u
e
u
r

f
x
e

u
t
i
l
i
s
a
n
t

l
e

j
e
u

d
e

c
a
r
.

n
a
t
i
o
n
a
l
1

c
a
r
.
2
5
5

c
a
r
.

A
Z
E
R
T
Y

C
L
O
C
N
C
L
O
B
L
O
B

d
e

t
y
p
e

c
a
r
a
c
t

r
e

m
o
n
o
-
o
c
t
e
t

o
u

m
u
l
t
i
-
o
c
t
e
t

u
t
i
l
i
s
a
n
t

l
e

j
e
u

d
e

c
a
r
.

n
a
t
i
o
n
a
l
1

o
c
t
e
t

4

g
i
g
a

c
a
r
.
B
L
O
B
B
L
O
B

!

g
r
o
s

o
b
j
e
t

b
i
n
a
i
r
e
1

o
c
t
e
t
4

g
i
g
a
-
o
c
t
e
t
s
B
F
I
L
E

P
o
i
n
t
e
u
r

v
e
r
s

u
n

f
c
h
i
e
r

b
i
n
a
i
r
e

e
x
t
e
r
n
e

1

o
c
t
e
t
4

g
i
g
a
-
o
c
t
e
t
s
T
I
M
E
S
T
A
M
P

(
f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n
)

D
a
t
e

(
a
n
n

e
,

m
o
i
s
,

e
t

j
o
u
r

p
l
u
s

h
e
u
r
e
,

m
i
n
u
t
e
,

s
e
c
o
n
d
e
s

e
t

q
u
a
n
t
i
t


d
e

f
r
a
c
t
i
o
n

d
e

s
e
c
o
n
d
e
)
,

o


f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n

e
s
t

l
e

n
o
m
b
r
e

d
e

c
h
i
f
f
r
e
s

d
e

l
a

p
a
r
t
i
e

f
r
a
c
t
i
o
n
n
a
i
r
e

d
e
s

s
e
c
o
n
d
e
s
.

L
e
s

v
a
l
e
u
r
s

v
o
n
t

d
e


0


9

(
1

p
o
u
r

l
e

d
i
x
i

m
e
,

2

p
o
u
r

l
e

c
e
n
t
i

m
e
,

)
.


L
a

v
a
l
e
u
r

p
a
r

d

f
a
u
t

e
s
t

6

(
l
e

m
i
l
l
i
o
n
i

m
e
)
.
T
I
M
E
S
T
A
M
P

(
f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n
)

W
I
T
H

L
O
C
A
L

T
I
M
E

Z
O
N
E
A
V
E
C

F
U
S
E
A
U

H
O
R
A
I
R
E

L
O
C
A
L

(
L
O
C
A
L

T
I
M
E

Z
O
N
E
)

T
o
u
t
e
s

l
e
s

v
a
l
e
u
r
s

d
o
n
n

e
s

d
a
n
s

l
e

f
u
s
e
a
u

h
o
r
a
i
r
e

l
o
c
a
l
,

a
v
e
c

l

e
x
c
e
p
t
i
o
n

s
u
i
v
a
n
t
e

:

l
e
s

d
o
n
n

e
s

s
o
n
t

n
o
r
m
a
l
i
s

e
s

d
a
n
s

l
e

f
u
s
e
a
u

d
e

l
a

b
a
s
e

l
o
r
s
q
u

e
l
l
e
s

y

s
o
n
t

s
t
o
c
-
k

e
s
.

L
o
r
s
q
u
e

l
e
s

d
o
n
n

e
s

s
o
n
t

r
e
l
u
e
s
,

e
l
l
e
s

s
o
n
t

c
o
n
v
e
r
t
i
e
s

d
a
n
s

l
e

f
u
s
e
a
u

h
o
r
a
i
r
e

l
o
c
a
l
.
Lrccr unc Iah|c (rcquIc S0L)
848 LhAPIJL 15 8asc dc donnccs
L
o
d
c

n
I
c
r
n
c

J
y
p
c
0
c
s
c
r

p
I

o
n
M

m
u
m
M
a
x

m
u
m
L
x
c
m
p
|
c
s

d
c

v
a
|
c
u
r
s
I
N
T
E
R
V
A
L

Y
E
A
R

(
y
e
a
r
_
p
r
e
c
i
s
i
o
n
)

T
O

M
O
N
T
H

S
t
o
c
k
e

e
n

p

r
i
o
d
e

d
e

t
e
m
p
s

e
n

a
n
n

e
s

e
t

m
o
i
s
,

o


y
e
a
r
_
p
r
e
c
i
s
i
o
n

e
s
t

l
e

n
o
m
b
r
e

c
h
i
f
f
r
e
s

p
o
u
r

l
e

n
o
m
b
r
e

d

a
n
n

e
s
.

D
e

0


9

c
h
i
f
f
r
e
s

a
p
r

s

l
a

v
i
r
g
u
l
e
.

L
a

v
a
l
e
u
r

p
a
r

d

f
a
u
t

e
s
t

2
.
I
N
T
E
R
V
A
L

D
A
Y

(
d
a
y
_
p
r
e
c
i
-
s
i
o
n
)

T
O

S
E
C
O
N
D

(
f
r
a
c
-
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n
)
S
t
o
c
k
e

u
n
e

p

r
i
o
d
e

d
e

t
e
m
p
s

e
n

j
o
u
r
s
,

h
e
u
r
e
s
,

m
i
n
u
t
e
s

e
t

s
e
c
o
n
d
e
s
,

o


d
a
y
_
p
r
e
c
i
s
i
o
n

e
s
t

l
e

n
o
m
b
r
e

m
a
x
i
m
u
m

d
e

c
h
i
f
f
r
e
s

p
o
u
r

l
e

n
o
m
b
r
e

d
e

j
o
u
r
s

(
d
e

0


9
,

e
t

2

p
a
r

d

f
a
u
t
)

e
t

f
r
a
c
t
i
o
n
a
l
_
s
e
c
o
n
d
s
_
p
r
e
c
i
s
i
o
n

e
s
t

l
e

n
o
m
b
r
e

d
e

c
h
i
f
f
r
e

a
p
r

s

l
a

v
i
r
g
u
l
e

p
o
u
r

l
e

n
o
m
b
r
e

d
e

s
e
c
o
n
d
e
s

(
d
e

0


9
,

e
t

6

p
a
r

d

f
a
u
t
)
.
U
R
O
W
I
D

[
(
s
i
z
e
)
]
A
d
r
e
s
s
e

l
o
g
i
q
u
e

d

u
n
e

l
i
g
n
e

(
c
h
a

n
e

d
e

c
a
r
a
c
t

r
e

e
n

b
a
s
e

6
4
)

d

u
n
e

t
a
b
l
e

o
r
g
a
n
i
-
s

e

e
n

i
n
d
e
x
.

L
a

t
a
i
l
l
e

(
o
p
t
i
o
n
n
e
l
l
e
)

e
s
t

c
e
l
l
e

d
e

l
a

c
o
l
o
n
n
e

d
e

t
y
p
e

U
R
O
W
I
D
.

L
a

t
a
i
l
l
e

m
a
x
i
m
a
l
e

e
s
t

d
e

4

0
0
0

o
c
t
e
t
s
.
841
Accder aux donnes dune table
(requte SQL)
SELECT * FROM NomDeLaTable
SELECT NomDeColonne[, ] FROM NomDeLaTable
Pour parcourir les donnes dune table, utilisez linstruc-
tion SELECT FROM Pour garder toutes les colonnes, uti-
lisez le caractre gnrique *.
Pour trier les donnes, utilisez loption ORDER BY suivie du
ou des noms de colonnes. Linstruction GROUP BY pour
regrouper des donnes entre elles.
En supposant que la table interroge contienne toutes les
ventes (montant de la vente dans la colonne Ventes )
effectues par toutes les boutiques (nom de la boutique
dans la colonne Boutique et ville de la boutique dans
la colonne Ville ), la requte suivante donne la recette
de chaque boutique en les classant dabord par ville puis
par boutique :
SELECT Ville, Boutique, SUM(Ventes)
FROM InfoBoutique
GROUP BY Boutique
ORDER_BY Ville, Boutique
La clause WHERE permet de fltrer les donnes pour ne
choisir que celles rpondant un certain critre. La clause
DISTINCT permet de ne faire apparatre quune seule fois
des entres identiques.
Par exemple, la requte suivante permet de slectionner
tous les magasins ayant effectu une vente dont le montant
se situe entre 500 et 700 euros. La clause DISTINCT permet
Acccdcr aux donnccs dunc Iah|c (rcquIc S0L)
848 LhAPIJL 15 8asc dc donnccs
de nobtenir quune seule fois le magasin (qui peut avoir
effectu plusieurs ventes de ce montant) :
SELECT DISTINCT Boutique
FROM InfoBoutique
WHERE Ventes >= 500 AND Ventes <= 700
Cette requte peut aussi scrire laide de linstruction
BETWEEN :
SELECT DISTINCT Boutique
FROM InfoBoutique
WHERE Ventes BETWEEN 500 AND 700
Enfn, supposer quune autre table contienne la rgion
dans laquelle se trouve une boutique, il est possible de
connatre les ventes par rgion en utilisant une jointure
interne avec la requte suivante :
SELECT DISTINCT A1.nom_de_region REGION, SUM(A2.
Ventes) VENTES
FROM Geographie A1, InfoBoutique A2
WHERE A1.Boutique == A2.Boutique
GROUP BY A1.nom_de_region
Ces quelques instructions SQL vous permettront de dbu-
ter rapidement. Pour aller plus loin, jetez un il sur le site
mentionn en introduction (http://sql.1keydata.com/fr).
840
Dfnir un environnement ODBC
(wxWidgets)
#include <wx/dbtable.h>
class wxDbConnectInf;
Pour se connecter une source ODBC, il faut fournir au
moins trois informations : un nom de source, un identifant
dutilisateur et un mot de passe. Une quatrime information,
un dossier par dfaut indiquant o sont stockes les don-
nes, est galement fournir pour des bases de donnes au
format texte ou dBase. La classe wxDbConnectInf est conue
pour embarquer ces donnes, ainsi que dautres ncessaires
pour certaines sources ODBC.
Le membre Henv est la cl (handle denvironnement) pour
accder une base. Le Dsn fourni doit imprativement et
exactement correspondre au nom de la base, tel quil
apparat dans la source ODBC (dans le panneau dadmi-
nistration ODBC sous Windows, ou dans le fchier .odbc.
ini par exemple). LUid est lidentifcation utilisateur uti-
liser pour se connecter la base. Il doit exister dans la base
vers laquelle vous souhaitez vous connecter. Il dtermi-
nera les droits et privilges de la connexion. Certaines
sources ODBC sont sensibles la casse, faites donc atten-
tion LAutStr est le mot de passe de lUid, l encore sen-
sible la casse. Le membre defaultDir est utile pour les
bases de donnes de type fchier. Cest par exemple le cas
des bases dBase, FoxPro ou fchier texte. Il contiendra un
chemin absolu, dans lequel vous aurez intrt utiliser des
/ plutt que des \ par souci de portabilit.
0cnr un cnvronncmcnI 008L (wxWdgcIs)
850 LhAPIJL 15 8asc dc donnccs
Se connecter une base
(wxWidgets)
class wxDb;
wxDb* wxDbGetConnection(wxDbConnectInf*);
Il y a deux faons de se connecter une base. Vous pouvez :
crer une instance de wxDb la main et ouvrir vous-
mme la connexion ;
utiliser les fonctions de mise en cache fournies avec
les classes wxODBC pour crer, maintenir et dtruire les
connexions.
Quelle que soit la mthode choisie, il faut dabord crer
un objet wxDbConnectInf. Le code suivant montre comment
lui fournir tous les paramtres ncessaires la future
connexion :
wxDbConnectInf dbConnectInf;
dbConnectInf.SetDsn(MonDsn);
dbConnectInf.SetUserID(MonNomDUtilisteur);
dbConnectInf.SetPassword(MonMotDePasse);
dbConnectInf.SetDefaultDir();
Pour allouer lenvironnement de connexion, la classe wxDb-
ConnectInf possde une mthode invoquer, comme le
montre la suite de lexemple. Une valeur de retour faux
signife un chec de lallocation et le handle est alors indfni.
if (dbConnectInf.AllocHenv())
{
wxMessageBox(Impossible dallouer lenvironnement ODBC,

ERROR de CONNEXION, wxOK


|
wxICON_EXCLAMATION);
return;
}
851
Un moyen plus concis consiste utiliser directement le
constructeur :
wxDbConnectInf *dbConnectInf = new wxDbConnectInf(NULL,

MonDsn,MonNomDUtilisteur, MonMotDePasse,

);
Ds que lenvironnement est cr, vous navez plus vous
proccuper de ce handle, mais seulement lutiliser. Il sera
libr lors de la destruction de linstance de la classe.
Nous parlions tout lheure de deux manires de crer
une connexion. La premire, manuelle, consiste crer
une instance de wxDb et louvrir :
wxDb* db = newDb(dbConnectInf->GetHenv());
bool opened = db->Open(dbConnectInf);
Lautre solution, plus avantageuse, consiste utiliser le sys-
tme de mise en cache fourni. Il offre les mmes possibili-
ts quune connexion manuelle, mais gre automatiquement
la connexion, de sa cration au nettoyage lors de sa ferme-
ture en passant par sa rutilisation. Et cela vous vite bien
sr de la coder vous-mme. Pour utiliser ce mcanisme,
appelez simplement la fonction wxDbGetConnection() :
wxDb* db = newDbGetConnection(dbConnectInf);
La valeur retourne pointe ainsi sur un wxDb la fois initia-
lis et ouvert. Si une erreur survient lors de la cration ou
de louverture, le pointeur retourn sera nul. Pour fermer
cette connexion, utilisez wxDbFreeConnection(db). Un appel
wxDbCloseConnections() vide le cache en fermant et
dtruisant toutes les connexions.
Sc connccIcr a unc hasc (wxWdgcIs)
852 LhAPIJL 15 8asc dc donnccs
Crer la dfnition de la table
et louvrir (wxWidgets)
class wxDbTable;
wxDbTable::wxDbTable(wxDb *pwxDb, const wxString

&tblName, const UWORD numColumns, const wxString

&qryTblName = , bool qryOnly = !wxDB_QUERY_ONLY,

const wxString &tblPath = )


Il est possible daccder au contenu des tables dune base
directement travers les nombreuses fonctions membres
de la classe wxDb. Heureusement, il existe une solution plus
simple, grce la classe wxDbTable qui encapsule tous ces
appels.
La premire tape consiste crer une instance de cette
classe, comme le montre le code suivant :
wxDbTable* table = new wxDbTable(db, tableName,

numTableColumns, , !wxDBQUERY_ONLY, );
Le premier paramtre est un pointeur sur une connexion
une base (wxDb*) ; le deuxime est le nom de la table ; le
troisime est le nombre de colonnes de la table (il ne doit
pas inclure la colonne ROWID si vous utilisez Oracle).
Viennent ensuite trois paramtres optionnels. qryTable-
Name est le nom de la table ou de la vue sur laquelle les
requtes porteront. Il permet dutiliser la vue au lieu de la
table elle-mme. Cela permet dobtenir de meilleures per-
formances dans le cas o les requtes impliquent plusieurs
tables avec plusieurs jointures. Nanmoins, toutes les
requtes INSERT, UPDATE et DELETE seront faites sur la table
de base. qryOnly indique si la table sera utilise uniquement
858
en lecture ou non. tblPath est le chemin indiquant o est
stocke la base. Cette information est indispensable pour
certains types de bases, comme dBase.
Info
Une table ouverte en lecture seule offre de meilleures perfor-
mances et une utilisation mmoire moindre. Si vous tes cer-
tain de ne pas avoir modifer son contenu, nhsitez pas
louvrir dans ce mode.
De plus, une table en lecture seule utilise moins de curseurs, et
certains types de base sont limits en nombre de curseurs
simultans une raison supplmentaire de faire attention.
Lorsque vous dfnissez les colonnes rcuprer, vous
pouvez conserver de une toutes les colonnes de la table.
table->SetColDefs(0, FIRST_NME, DB_DATA_TYPE_VARCHAR,

FirstName, SQL_C_WXCHAR, sizeof(FirstName), true, true);


table->SetColDefs(
1, // numro de colonne dans la table
LAST_NAME, // nom de la colonne dans la base/requte
DB_DATA_TYPE_VARCHAR, // type de donne
LastName, // pointeur sur la variable lier
SQL_C_WXCHAR, // type de conversion
sizeof(LastName), // taille max de la variable lie
true, // optionnel, indique si cest une cl (faux

par dfaut)
true // optionnel, mise jour autorise (vrai

par dfaut)
);
Lrccr |a dcnIon dc |a Iah|c cI |ouvrr (wxWdgcIs)
854 LhAPIJL 15 8asc dc donnccs
La dfnition des colonnes commence lindice 0 jusquau
nombre 1 de colonnes spcif lors de la cration de
linstance de wxDbTable. Les lignes de codes ci-avant lient les
colonnes mentionnes de la table des variables de lappli-
cation. Ainsi, lorsque lapplication appelle wxDbTable::
GetNext() (ou nimporte quelle fonction rcuprant des
donnes dans lensemble rsultat), les variables lies aux
colonnes contiendront les valeurs correspondantes.
Les variables lies ne contiennent aucune valeur tant
quaucune Get...() nest appel. Mme aprs un appel
Query() le contenu des variables lies est indtermin. Vous
pouvez avoir autant dinstances de wxDbTable que souhait
sur la mme table.
Louverture de la table se contente de vrifer si la table
existe vraiment, que lutilisateur a au moins un privilge
de lecture (clause SELECT), rserve les curseurs ncessaires,
lie les colonnes aux variables comme spcif et construit
une instruction dinsertion par dfaut (clause INSERT) si la
table nest pas ouverte en lecture seule.
if (!table->Open())
{
// une erreur est survenue lors de louverture
}
La seule raison relle dun chec est que lutilisateur
na pas les privilges requis. Dautres problmes, comme
limpossibilit de lier les colonnes aux variables seront
plutt dus des problmes de ressources (comme la
mmoire). Toute erreur gnre par wxDbTable::Open() est
journalise dans un fchier si les fonctions de journalisa-
tion (logging) SQL sont actives.
855
Utiliser la table (wxWidgets)
bool WxDbTable::Query();
Pour utiliser la table et la dfnition ainsi cre, il faut
maintenant dfnir les donnes collecter.
Le code suivant montre comment charger une requte
SQL dans cette table :
table->SetWhereClause(FIRST_NAME = GEORGE);
table->SetOrderByClause(LAST_NAME, AGE);
table->SetFromClause();
Si vous souhaitez obtenir un classement invers ajoutez DESC
aprs le nom de la colonne, par exemple : LAST_NAME DESC.
La clause FROM permet de crer des jointures. Lorsquelle est
vide, on utilise directement la table de base.
Aprs avoir spcif tous les critres ncessaires, il sufft de
lancer la requte, comme le montre le code suivant :
if (!table->Query())
{
// erreur survenue pendant lexcution de la requte
}
Bien souvent, lerreur provient dun problme de syntaxe
dans la clause WHERE. Pour trouver lerreur, regardez le
contenu du membre erreurList[] de la connexion. En cas
de succs, cela signife que la requte sest bien droule,
mais le rsultat peut tre vide (cela dpend de la requte).
uI|scr |a Iah|c (wxWdgcIs)
858 LhAPIJL 15 8asc dc donnccs
Il est maintenant possible de rcuprer les donnes. Le
code suivant montre comment lire toutes les lignes du
rsultat de la requte :
wxString msg;
while (table->GetNext())
{
msg.Printf(Line #%lu Nom: %s Prnom: %s,

table->GetRowNum(), FirstName, LastName);


wxMessageBox(msg, Donnes, wxOK


|
wxICON_

INFORMATION, NULL);
}
Fermer la table (wxWidgets)
if (table)
{
delete table;
table = NULL;
}
Fermer une table est aussi simple que de dtruire son ins-
tance. La destruction libre tous les curseurs associs, dtruit
les dfnitions de colonnes et libre les handles SQL utiliss
par la table, mais pas lenvironnement de connexion.
851 Fcrmcr |a conncxon a |a hasc (wxWdgcIs)
Fermer la connexion la base
(wxWidgets)
wxDb::Close();
wxDbFreeConnection(wxDb*);
wxDbCloseConnections();
Lorsque toutes les tables utilisant une connexion donne
ont t fermes, vous pouvez fermer cette connexion. La
mthode employer dpend de la faon dont vous avez
cr cette connexion.
Si la connexion a t cre manuellement, vous devez la
fermer ainsi :
if (db)
{
db->Close();
delete db;
db = NULL;
}
Si elle a t obtenue par la fonction wxDbGetConnection()
qui gre un systme de cache, vous devez alors fermer
cette connexion comme suit :
if (db)
{
wxDbFreeConnection(db);
db = NULL;
}
858 LhAPIJL 15 8asc dc donnccs
Notez que le code ci-dessus libre juste la connexion de
telle sorte quelle puisse tre rutilise par un prochain
appel wxDbGetConnection(). Pour librer toutes les res-
sources, vous devez appeler le code suivant :
wxDbCloseConnections();
Librer lenvironnement ODBC
(wxWidgets)
wxDbConnectInf::FreeHenv();
Une fois toutes les connexions fermes, vous pouvez lib-
rer lenvironnement ODBC :
dbConnectInf->FreeHenv();
Si vous avez utilis la version du constructeur avec tous les
paramtres, la destruction de linstance libre lenvironne-
ment automatiquement :
delete dbConnectInf;
16
XML
XML (Extensible Markup Language) est un langage infor-
matique de balisage gnrique de plus en plus rpandu. Il
existe principalement deux types dAPI pour la manipula-
tion de fchiers XML :
DOM (Document Object Modeling). Constitue un objet
mmoire de la totalit dun document XML. Cette API
permet un accs direct tous les nuds de larbre (l-
ments, texte, attributs) pour les lire, les modifer, les
supprimer ou en ajouter. Il est par exemple trs utilis
avec JavaScript dans les navigateurs web.
SAX (Simple API for XML). Systme de traitement
squentiel. Il reprsente une relle alternative DOM
pour les fchiers XML volumineux. Lors de la lecture
dun fchier XML avec SAX, il est possible de ragir
diffrents vnements comme louverture et la ferme-
ture dune balise. Il est galement possible de gnrer
des vnements SAX, par exemple lors de la lecture du
contenu dune base de donnes, afn de produire un
document XML.
880 LhAPIJL 18 XML
Il existe diffrentes bibliothques permettant de manipu-
ler des documents XML. En voici quelques-unes parmi
les plus rpandues, en rapport avec le C++ :
MSXML (Microsoft Core XML Services). Trs rpandue,
ne fonctionne toutefois que sous Windows.
libXML2 (http://www.xmlsof.org). Bibliothque C
trs rpandue dans le monde GNU/Linux. Disponible
pour Linux, Winodws, Solaris, Mac OS X, HP-UX,
AIX. Vous pouvez bien sr lutiliser avec C++.
Xerces-C++ (http://xerces.apache.org/xerces-c).
Implmente des analyseurs (parser) DOM, SAX et SAX2.
Disponible pour Windows, Unix/Linux/Mac OS X et
Cygwin.
eXpat (http://expat.sourceforge.net). Bibliothque
crite en C utilise par Firefox (disponibles sur les mmes
plate-formes que Firefox). Il existe des ponts (wrappers)
C++ de cette bibliothque.
Dautres bibliothques haut niveau comme QT (http://
www.trolltech.com) et wxWxWidgets (http://www.
wxwidgets.org) fournissent galement leur API pour le
traitement des fchiers XML. Ce chapitre prsente lutili-
sation des objets fournis par wxWidgets. Ils utilisent un
modle DOM.
Charger un fchier XML
#include <wx/xml/xml.h>
class WXDLLIMPEXP_XML wxXmlDocument : public wxObject
{
public:
wxXmlDocument();
wxXmlDocument(const wxString& flename,
const wxString& encoding = wxT(UTF-8));
881
wxXmlDocument(wxInputStream& stream,
const wxString& encoding = wxT(UTF-8));
virtual ~wxXmlDocument();

wxXmlDocument(const wxXmlDocument& doc);
wxXmlDocument& operator=(const wxXmlDocum
// Lit un fchier XML et charge son contenu.
// Retourne TRUE en cas de succs, FALSE sinon.
virtual bool Load(const wxString& flename,
const wxString& encoding = wxT(UTF-8),
int fags = wxXMLDOC_NONE);
virtual bool Load(wxInputStream& stream,
const wxString& encoding = wxT(UTF-8),
int fags = wxXMLDOC_NONE);
wxXmlDocument& operator=(const wxXmlDocum
// Enregistre le document dans un fchier XML.
virtual bool Save(const wxString& flename,
int indentstep = 1) const;
virtual bool Save(wxOutputStream& stream,
int indentstep = 1) const;
bool IsOk() const;
wxXmlDocument& operator=(const wxXmlDocum
// Retourne le nud racine du document.
wxXmlNode *GetRoot() const;
wxXmlDocument& operator=(const wxXmlDocum
// Retourne la version du document (peut tre vide).
wxString GetVersion() const;
wxXmlDocument& operator=(const wxXmlDocum
// Retourne lencodage du document (peut tre vide).
// Note : il sagit de lencodage du fchier,
// et non lencodage une fois charg en mmoire !
wxString GetFileEncoding() const;
wxXmlDocument& operator=(const wxXmlDocum
// Mthodes dcriture :
wxXmlNode *DetachRoot();
void SetRoot(wxXmlNode *node);
void SetVersion(const wxString& version);
void SetFileEncoding(const wxString& encoding);

#if !wxUSE_UNICODE
// Retourne lencodage de la reprsentation mmoire du
Lhargcr un chcr XML
882 LhAPIJL 18 XML
// document (le mme que fourni la fonction Load
// ou au constructeur, UTF-8 par dfaut).
// NB : cela na pas de sens avec une compilation
// Unicode o les donnes sont stockes en wchar_t*
wxString GetEncoding() const;
void SetEncoding(const wxString& enc);
#endif

private:
// ...
};
La classe wxXmlDocument utilise la bibliothque expat pour
lire et charger les fux XML. Lexemple suivant charge un
fchier XML en mmoire :
wxXmlDocument doc;
if (!doc.Load(wxT(fchier.xml)))
{
// Problme lors du chargement
}
Aprs cela, votre fchier se trouve en mmoire sous forme
arborescente. Si vous souhaitez garder tous les espaces et
les indentations, vous pouvez dsactiver leur suppression
automatique. Lexemple suivant montre comment :
wxXmlDocument doc;
if (!doc.Load(wxT(fchier.xml), wxT(UTF-8),

wxXMLDOC_KEEP_WHITESPACE_NODES))
{
// Problme lors du chargement
}
888
Vous pouvez faire de mme lors de lenregistrement du
document dans un fchier :
doc.Save(wxT(fchier.xml), wxXMLDOC_KEEP_WHITESPACE

_NODES);
Manipuler des donnes XML
// Proprit(es) dun nud XML.
// Exemple : in <img src=hello.gif id=3/>
// src est une proprit ayant hello.gif pour
// valeur et id une autre ayant la valeur 3.

class WXDLLIMPEXP_XML wxXmlProperty
{
public:
wxXmlProperty();
wxXmlProperty(const wxString& name, const

wxString& value, wxXmlProperty *next = NULL);


virtual ~wxXmlProperty();

wxString GetName() const;
wxString GetValue() const;
wxXmlProperty *GetNext() const;

void SetName(const wxString& name);
void SetValue(const wxString& value);
void SetNext(wxXmlProperty *next);
private:
// ...
};
Manpu|cr dcs donnccs XM
884 LhAPIJL 18 XML
// Un nud dun document XML.
class WXDLLIMPEXP_XML wxXmlNode
{
public:
wxXmlNode();
wxXmlNode(wxXmlNode* parent,
wxXmlNodeType type,
const wxString& name,
const wxString& content = wxEmptyString,
wxXmlProperty* props = NULL,
wxXmlNode* next = NULL);
wxXmlNode(wxXmlNodeType type,
const wxString& name,
const wxString& content = wxEmptyString);
virtual ~wxXmlNode();

// Constructeur par copie et oprateur de copie.
wxXmlNode(const wxXmlNode& node);
wxXmlNode& operator=(const wxXmlNode& node);

virtual void AddChild(wxXmlNode *child);
virtual bool InsertChild(wxXmlNode *child,
wxXmlNode *followingNode);
#if wxABI_VERSION >= 20808
bool InsertChildAfter(wxXmlNode *child,
wxXmlNode *precedingNode);
#endif
virtual bool RemoveChild(wxXmlNode *child);
virtual void AddProperty(const wxString& name,
const wxString& value);
virtual bool DeleteProperty(const wxString& name);

// Accesseurs :
wxXmlNodeType GetType() const;
wxString GetName() const;
wxString GetContent() const;

int GetDepth(wxXmlNode *grandparent = NULL) const;

bool IsWhitespaceOnly() const;
885
// Rcupre le contenu dun nud wxXML_ENTITY_NODE
// En effet, <tag>contenu<tag> est reprsent comme
// wxXML_ENTITY_NODE name=tag, content=
//
|
__ wxXML_TEXT_NODE or
// wxXML_CDATA_SECTION_NODE name=
content=contenu
wxString GetNodeContent() const;

wxXmlNode *GetParent() const;
wxXmlNode *GetNext() const;
wxXmlNode *GetChildren() const;

wxXmlProperty *GetProperties() const;
bool GetPropVal(const wxString& propName,
wxString *value) const;
wxString GetPropVal(const wxString& propName,
const wxString& defaultVal)
const;
bool HasProp(const wxString& propName) const;

void SetType(wxXmlNodeType type);
void SetName(const wxString& name);
void SetContent(const wxString& con);

void SetParent(wxXmlNode *parent);
void SetNext(wxXmlNode *next);
void SetChildren(wxXmlNode *child);

void SetProperties(wxXmlProperty *prop);
virtual void AddProperty(wxXmlProperty *prop);

private:
// ...
Un nud XML (wxXmlNode) a un nom et peut avoir un
contenu et des proprits. La plupart des nuds sont de
type wxXML_TEXT_NODE (pas de nom ni de proprits) ou
wxXML_ELEMENT_NODE. Par exemple, avec <title>hi</title>,
Manpu|cr dcs donnccs XM
888 LhAPIJL 18 XML
on obtient un nud lment ayant pour nom title (sans
contenu) possdant pour seul fls un nud texte ayant
pour contenu hi .
Si wxUSE_UNICODE vaut 0, toutes les chanes seront encodes
avec la page de codes spcife lors de lappel la fonction
Load() du document XML (UTF-8 par dfaut).
Info
Le constructeur par copie affecte toujours le pointeur sur le
parent et le pointeur sur le suivant NULL.
Loprateur daffectation (=) ne recopie ni le pointeur sur le
parent ni le pointeur sur le suivant, mais les laissent inchangs.
Par contre, il recopie toute larborescence du nud concern
(fls et proprits).
Lexemple suivant illustre comment utiliser ces diffrentes
classes XML :
wxXmlDocument doc;
if ( ! doc.Load(wxT(myfle.xml)) )
return false;

// Dbut du traitement du fchier XML
if ( doc.GetRoot()->GetName() != wxT(mon-noeud-racine) )
return false;

wxXmlNode *child = doc.GetRoot()->GetChildren();
while (child)
{
if (child->GetName() == wxT(tag1))
{
// process text enclosed by <tag1></tag1>
wxString content = child->GetNodeContent();

...

// process properties of <tag1>
wxString propvalue1 =
881

child->GetPropVal(wxT(prop1),
wxT(default-value));
wxString propvalue2 =

child->GetPropVal(wxT(prop2),
wxT(default-value));

...
}
else if (child->GetName() == wxT(tag2))
{
// process tag2 ...
}
child = child->GetNext();
}
Le contenu dun nud diffre selon son type. Le tableau
suivant vous aidera savoir de quel type de nud il sagit.
wxXmlNodeType : types de nud XML
Nom va|cur
wxXML_ELEMENT_NODE 1
wxXML_ATTRIBUTE_NODE 2
wxXML_TEXT_NODE 3
wxXML_CDATA_SECTION_NODE 4
wxXML_ENTITY_REF_NODE 5
wxXML_ENTITY_NODE 6
wxXML_PI_NODE 7
wxXML_COMMENT_NODE 8
wxXML_DOCUMENT_NODE 9
wxXML_DOCUMENT_TYPE_NODE 10
wxXML_DOCUMENT_FRAG_NODE 11
wxXML_NOTATION_NODE 12
wxXML_HTML_DOCUMENT_NODE 13
* Ces noms et valeurs correspondent lnumration xmlElementType de
la bibliothque libXML.
Manpu|cr dcs donnccs XM
Annexe A
8h|oIhcqucs cI
comp|aIcurs
Compilateurs
Borland Turbo C++ et C++ Builder
Turbo C++ : http://cc.codegear.com/free/turbo, gratuit
C++ Builder : http://www.codegear.com/products/
cppbuilder, commercial
Systmes : Windows
La qualit des compilateurs Borland est bien connue. C++
Builder est un vrai IDE (environnement de dveloppement
intgr) RAD, comme Delphi mais en C++. Un must. La
version 2009 inclut le support du C++0x.
Microsoft Visual Studio
Site : http://msdn.microsoft.com/en-us/visualc/
default.aspx
Systmes : Windows
810 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
Depuis quelque temps maintenant, la version express de
Visual Studio C++ est gratuite. Elle peut mme tre utili-
se pour crer des applications commerciales.
GCC GNU Compiler Collection
Site : http://gcc.gnu.org
Systmes : Windows (cygwin et mingw), Linux
Le compilateur libre par excellence.
Intel C++
Site : http://www.intel.com/cd/software/products/
asmo-na/eng/compilers/284132.htm
Systmes : Windows, Linux, Mac OS X
Processeur : Intel seulement
Pour ceux dont les performances du code produit sont
essentielles
IDE et RAD
Dev-C++ IDE et compilateur
Site : http://www.bloodshed.net/devcpp.html
http://wxdsgn.sourceforge.net (version RAD avec
wxWidgets)
Licence : Sources de lapplication (en Delphi) disponibles
en GPL
Systmes : Windows
Compilateurs : IDE pour Mingw ou GCC
Dev-C++ est un IDE libre pour programmer en C/C++.
Facile dinstallation (une version inclut mme le compila-
teur Mingw) et pratique (intgration du dbogueur GDB),
811
il est le compagnon idal pour ceux qui veulent un IDE
simple et rapide. Et il est parfait pour ceux qui veulent
dbuter rapidement.
WxDevC++ est plus jour que DevC++. De plus, cette
version contient les packs WxWindows installs par dfaut.
KDevelop IDE
Site : http://www.kdevelop.org
Licence : GPL
Systmes : Linux, Solaris, Unix
Compilateurs : GCC
Le projet KDevelop a t mis en place en 1998 pour btir
un IDE pour KDE facile utiliser. Depuis, KDevelop est
disponible pour le public sous la licence GPL et supporte
beaucoup de langages de programmation.
KDE tant dvelopp avec la bibliothque QT, cet envi-
ronnement va peut-tre enfn devenir disponible pour
Windows. suivre car cest un IDE trs largement uti-
lis et dune grande qualit.
Ultimate++ Bibliothque graphique et suite RAD
Site : http://www.ultimatepp.org
Licence : BSD
Systmes : Windows, Linux, (version Mac OS X via X11
en cours de dveloppement ; WinCE prvue ; Solaris et
autres systme BSD envisages)
Compilateurs : MingGW, Visual (2003+), GCC
Ultimate++ est plus quune bibliothque, cest une suite
de dveloppement ayant pour ambition la productivit du
dveloppeur. Cette suite comprend un ensemble de biblio-
thque (IHM, SQL, etc.) et un IDE (environnement de
I0L cI A0
812 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
dveloppement intgr). La rapidit de dveloppement
que procure cette bibliothque provient dun usage agres-
sif des possibilits quoffre le C++, plutt que de miser sur
un gnrateur de code (comme QT le fait, par exemple).
TheIDE, lIDE RAD de cette suite, utilise la technologie
BLITZ build pour rduire jusqu quatre fois le temps de
compilation. Elle propose galement : un outil de concep-
tion visuel dinterface ; Topic++, un outil de documenta-
tion de code et de documentation dapplication ; Assist++,
un analyseur de code C++ apportant un systme de com-
pltion automatique de code, de navigation dans le code,
et une approche de transformation (refactoring) de code.
Si cet environnement vous tente, nhsitez pas Il a tout
pour devenir incontournable (il ne lui manque que le sup-
port de Mac OS X en natif Cocoa).
Autres
Borland C++ Builder (voir Compilateurs)
Code::Block (http:// www.codeblocks.org)
Eclipse (http://www.eclipse.org)
XCode (fourni avec le systme dexploitation Mac
OS X)
Bibliothques
POCO C++ Dveloppement rseau et XML
Site : http://pocoproject.org/poco/info/index.html
Licence : Boost Software (licence libre pour le commercial
et lopen source)
Systmes : Windows, Mac OS X, Linux, HP UX, Tru64,
Solaris, QNX, plus Windows CE et tout systme embar-
qu compatible POSIX.
818
Compilateurs : Dec CC, Visual C++, GCC, HP C++,
IBM xlC, Sun CC
POCO C++ (C++ Portable Components) est une collec-
tion de bibliothques de classes pour le dveloppement
dapplications portables, orientes rseau. Ses classes sint-
grent parfaitement avec la bibliothque standard STL et
couvrent de multiples fonctionnalits : threads, synchroni-
sation de threads, accs fchiers, fux, bibliothques partages
et leur chargement, sockets et protocoles rseau (HTTP,
FTP, SMTP, etc.), serveurs HTTP et parseurs XML avec
interfaces SAX2 et DOM.
Blitz++ Calcul scientifque en C++
Site : http://www.oonumerics.org/blitz
Licence : GPL ou Blitz artistic License
Systmes : Linux, Sparc, SGI Irix, Cray, IBM AIX, Solaris,
HP UX, Sun, Unix, Dec Alpha, Dec Ultrix.
Compilateurs : GCC, Visual C++ (2003+), Intel C++,
CRI C++ (Cray), HP C++, KAI C++, etc.
Blitz++ est une bibliothque C++ pour le calcul scienti-
fque. Elle utilise les templates pour atteindre un niveau de
performances proche du Fortran 77/90 (et parfois mme
meilleur).
ColDet Dtection de collision 3D
Site : http://photoneffect.com/coldet
Licence : LGPL
Systmes : Linux, Windows, Mac OS X, etc.
Compilateurs : Visual C++, Borland C++ Builder, GCC,
MetroWerks CodeWarrior, etc.
Cette bibliothque apporte une solution libre au problme
de dtection de collision entre polydres gnriques. Elle vise
8h|oIhcqucs
814 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
la programmation des jeux 3D o lexactitude de la dtec-
tion entre deux objets complexes est requise. Cette biblio-
thque fonctionne sur tout type de modles, y compris
des soupes de polygones. Elle utilise une hirarchie de
botes englobantes pour optimiser la dtection, puis un
test dintersection sur les triangles pour lexactitude. Elle
fournit mme, sur demande, le point exact de la collision
et les paires de triangles sintersectant. Un systme de
timeout peut tre mis en place pour interrompre des calculs
trop longs. Il est galement possible de faire des tests din-
tersection de type lanc de rayon-modle, segment-
modle, et dutiliser directement les primitives de test de
collision lanc de rayon-sphre et sphre-sphre.
CGAL Computational Geometry Algorithms Library
Site : http://www.cgal.org
Licence : LGPL/QPL (selon les parties utilises) ou com-
merciale
Systmes : Windows, Linux, Mac OS X, Solaris, SGI Irix
Compilateurs : Visual C++, Borland C++, GCC, Intel
C++, SunPro, SGI CC, KAI C++
CGAL est une bibliothque de structures et de calculs
gomtriques srs et effcaces. Parmi ceux-ci on trouve :
les triangulations (2D contraintes ou de Delaunay 2D/3D),
les diagrammes de Vorono (points 23/3D, points massi-
ques 2D, segments), les oprations boolennes sur les poly-
dres, les arrangements de courbes et leurs applications
(enveloppes 2D/3D, sommes de Minkowski), la gnra-
tion de maillage (maillages de Delaunay 2D et 3D, peaux),
le calcul de gomtries (simplifcation de maillage de sur-
face, subdivision et paramtrisation, estimation des pro-
prits diffrentielles locales, approximation de crtes et
dombiliques), alpha-formes, interpolations, collages, dis-
tances, structures de recherche, etc.
815
Dinkum Compleat Library Standard C++, C99, and
Embedded C++
Site : http://www.dinkumware.com
Licence : Commercial
Systmes : Windows, Linux, Mac OS X, Solaris
Compilateurs : Visual C++, GCC, SunC++, Embedded
Visual C++
Cette bibliothque est une rimplmentation de la biblio-
thque standard STL, en y ajoutant le support/mulation
du C99 en plus de lISO 14882:1998/2003 et du TR1.
Elle met laccent sur la portabilit et les performances. Elle
rassemble galement dautres fonctionnalits quil faut
glaner dans dautres bibliothques. Cest une bonne solu-
tion pour ceux qui en ont les moyens, condition quelle
ne fasse pas double emploi avec une autre solution.
GC Garbage Collector for C/C++
Site : http://www.hpl.hp.com/personal/
Hans_Boehm/ gc
Systmes : Linux, *BSD, Windows, Mac OS X, HP-UX,
Solaris, Tru64, IRIX, etc.
Si vous tes fatigu de grer la mmoire et avez la possibi-
lit de mettre en place un systme de ramasse-miette, alors
essayez cette bibliothque. Elle est utilise par le projet
Mozilla (comme dtecteur de perte de mmoire), le projet
Mono, le compilateur statique Java GCJ, le runtime
Objective C de GNU, et bien dautres.
GMP GNU Multiprecision Package
Site : http://gmplib.org
Licence : LGPL
8h|oIhcqucs
818 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
Processeurs : AMD64, POWER64, POWER5, PPC970,
Alpha, Itanium, x86,
Compilateurs : Compilateur C/C++ standard
GMP, ou GNUmp, est une bibliothque implmentant
des nombres entiers signs, des nombres rationnels et des
nombres virgule fottante en prcision arbitraire. Toutes
les fonctions ont une interface normalise. GMP est
conue pour tre aussi rapide que possible en utilisant les
mots machine comme type arithmtique de base, en utili-
sant des algorithmes rapides, en optimisant soigneusement
le code assembleur pour les boucles intrieures les plus
communes, et par une attention gnrale porte la vitesse
(par opposition la simplicit ou llgance).
LEDA Library of Effcient Data types and Algorithms
Site : http://www.algorithmic-solutions.com/leda
Licence : Gratuite, professionnel, recherche (le contenu
diffre selon la licence)
Systmes : Windows, Linux, Solaris
Compilateurs : Visual C++ (2005+), GCC (3.4+),
SunPRO (5.8)
LEDA est une immense bibliothque de structures de don-
nes et dalgorithmes gomtriques et combinatoires. Elle
est utilise par certains industrielles pour raliser des bancs
dessais sur de grands jeux de donnes. Elle fournit une col-
lection considrable de structures de donnes et dalgorith-
mes sous une forme qui leur permet dtre employs par
des non-experts. Dans la version en cours, cette collection
inclut la plupart des structures et algorithmes classiques du
domaine. LEDA contient des implmentations effcaces
pour chacun de ces types de donnes, par exemple, piles
de Fibonacci pour des fles dattente prioritaires, tables
811
dynamiques dadressage dispers parfait (dynamic perfect
hashing) pour les dictionnaires, etc. Un atout majeur de
LEDA est son implmentation des graphes. Elle offre les
itrations standard telles que pour tous les nuds v dun
graphe G ou encore pour tous les voisins W de v ; elle
permet dajouter et deffacer des sommets et des artes, den
manipuler les matrices dincidence, etc.
Pantheios C++ Logging
Site : http://www.pantheios.org
Licence : type BSD
Systmes : Windows, Linux, Mac OS X, Unix
Compilateurs : Borland (5.5.1+), Comeau (4.3.3+), Digital
Mars (8.45+), GCC (3.2+), Intel (6+), Metrowerks (8+),
Microsoft Visual C++ (5.0+)
Pantheios est une bibliothque de journalisation (logging)
offrant un bon quilibre entre contrle des types, perfor-
mances, gnricit et extensibilit. La portabilit de cette
bibliothque est galement un atout.
Elle offre un systme de fltrage des messages en fonction
des huit niveaux de svrit dfnis par le protocole SysLog
(RFC 3164, voir http://fr.wikipedia.org/wiki/Syslog
et http://tools.ietf.org/html/rfc3164), sans pour autant
vous limiter ceux-ci (vous pouvez dfnir les vtres). Elle
fournit un grand nombre de plug-in dcriture : fchier,
stderr/stdout, SysLog (avec une implmentation person-
nalise du protocole SysLog pour Windows), dbogueur
Windows, journal dvnement Windows, objet derreur
COM, et vous pouvez en crire dautres.
La socit Synesis Software (http://synesis.com.au)
offre de personnaliser Pantheios selon vos besoins.
8h|oIhcqucs
818 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
STLport Bibliothque standard alternative
Site : http://www.stlport.org
Licence : libre
Compilateurs :
SUN Workshop C++ Compilers 4.0.x-5.0, 5.1, 5.2
(Forte 6, 6u1, 6u2), for Solaris
GNU GCC 2.7.2-2.95, 3.0 Compilers, for all GCC
platforms
IBM xlC 3.1.4.0, for AIX
IBM OS/390 C/C++ 1.x - 2.x Compiler, for OS/390
(STLport is the only available and offcial ANSI library
for this platform)
IBM VisualAge/ILE C++ for AS/400 Version 4 Release
4, for AS/400
IBM Visual Age C++ 3.x-5.x, for OS/2 and Win32
HP ANSI C++ Compiler, for HP-UX
SGI MIPSpro C++ 7.x, for IRIX
SGI MIPSpro C++ 4.0, for IRIX
DEC C++ V5.5-004, V6.x for OSF 3.2/4.0, for Digital
Unix.
Tandem NCC, for Tandem OS
SCO UDK C++, for UnixWare
Apogee C++ 4.0, for SUN Solaris
KAI C++ 3.1-4.x, for all KAI platforms
Portland Group C++ compiler ( pgCC), for all pgCC
platforms
Microsoft Visual C++ 4.x - 6.x, for Win32
Microsoft Embedded Visual C++ 3.0
Borland C++ 5.02-5.5, for Win16/32
810
Metrowerks CodeWarrior Pro 1.8-5.3, for Mac OS,
Win32
Intel (R) C++ 4.0/4.5/5.0 Reference Compiler, for
Win32
Watcom C++ 10.x-11.0, for DOS, Win16, Win32
Powersoft's Power++ 2.0, for Win32
Symantec C++ 7x/8.x, for MacOS and Win32
Apple MPW MrCpp and SCpp compilers, for Mac OS
STLport se distingue des STL fournit par la plupart de com-
pilateurs, notamment en intgrant un mode de dbogage
la STL laide ditrateurs srs et de prconditions
permettant un contrle rigoureux lors de lexcution.
Ne cherchez pas plus loin si votre compilateur ne contient
pas la bibliothque standard STL.
Bibliothques dominante
graphique
SDL Simple DirectMedia Layer
Site : http://www.libsdl.org
Licence : LGPL (et aussi commerciale avec support pour
ceux qui le souhaitent)
Systmes : Linux, Windows, Windows CE, BeOS, Mac Os,
Mac Os X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris,
IRIX et QNX. Le support dautres systmes (AmigaOS,
Dreamcast, AIX, OSF/Tru64, RISC OS, SymbianOS et
OS/2) semble exister mais non offciellement
Compilateurs : Tout compilateur C
8h|oIhcqucs a domnanIc graphquc
880 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
Simple DirectMedia Layer est une bibliothque multimdia
multiplate-forme. Elle fournit un accs bas niveau au mat-
riel audio, clavier, souris, joystick, 3D ( travers OpenGL) et
tampon vido 2D. Elle est utilise par des applications de
lecture MPEG, des mulateurs, bon nombre de jeux populai-
res (dont le port Linux de Civilization : Call To Power ).
SDL est crite en C, mais fonctionne nativement en C++.
Il existe aussi des ponts vers quantit de langages tels Ada,
C#, D, Eiffel, Erlang, Euphoria, Guile, Haskell, Java, Lisp,
Lua, ML, Objective C, Pascal, Perl, PHP, Pike, Pliant,
Python, Ruby, Smalltalk et Tcl.
wxWidgets Dveloppement multiplate-forme et IHM
Site : http://www.wxwidgets.org
Licence : wxWidgets Library Licence (proche de la LPGL)
Systmes : Mac OS X, GNU/Linux et Unix, Microsoft
Windows, OS/2, ainsi que pour du matriel embarqu
(embedded) sous GNU/Linux ou Windows CE
Compilateurs : Tout compilateur C++ standard
wxWidgets (anciennement wxWindows) est une biblio-
thque graphique libre utilise comme bote outils de
programmation dinterfaces utilisateur multiplate-formes.
la diffrence dautres botes outils qui tentent de resti-
tuer une interface utilisateur identique sur toutes les plate-
formes, wxWidgets restitue des abstractions comparables,
mais avec lapparence native de chaque environnement cible,
ce qui est moins dpaysant pour les utilisateurs fnaux.
La bibliothque originale est crite en C++ mais il existe de
nombreux ponts vers les langages de programmation cou-
rants : Python wxPython ; Perl wxPerl ; BASIC wxBasic ;
Lua wxLua ; OCaml wxCaml ; JavaScript wxJava-
Script ; Java wxJava ou wx4j ; Ruby wxRuby ; Eiffel
881
wxEiffel ; Haskell wxHaskell ; C#/.NET wx.NET ;
Euphoria wxEuphoria ; D wxD. Certains sont plus dve-
lopps que dautres et les plus populaires restent wxPython,
wxPerl et wxBasic.
Sous le nom wx , wxWidgets est la base de linterface
utilisateur des applications dveloppes avec C++BuilderX
(qui nest malheureusement plus disponible) de Borland.
QT Dveloppement multiplate-forme et IHM
Site : http://trolltech.com/products
Licence : QPL
Systmes : Linux, Windows, Windows CE, Mac OS X, Unix
Compilateurs : Tout compilateur C++ standard
Qt est une bibliothque logicielle oriente objet et dve-
loppe en C++. Elle offre des composants dinterface gra-
phique (widgets), daccs aux donnes, de connexions
rseau, de gestion des fls dexcution, danalyse XML, etc.
Qt permet la portabilit des applications qui nutilisent
que ses composants par simple recompilation du code
source. Les environnements supports sont les Unix (dont
Linux) utilisant le systme graphique X Window System,
Windows et Mac OS X.
Qt est notamment connue pour tre la bibliothque sur
laquelle repose lenvironnement graphique KDE, lun des
environnements de bureau les plus utiliss dans le monde
Linux.
De plus en plus de dveloppeurs utilisent Qt, y compris
parmi de grandes entreprises. On peut notamment citer
Google, Adobe Systems ou encore la NASA.
8h|oIhcqucs a domnanIc graphquc
882 ANNLXL A 8h|oIhcqucs cI comp|aIcurs
ILOG VIEWS Bibliothque C++ et diteur
pour concevoir de trs grosses IHM
Site : http://www.ilog.com/products/views
Licence : Commerciale
Systmes : Windows, Unix (SUN-Solaris, HP-UX, IMB-
AIX), Linux
ILOG VIEWS est une bibliothque C++ haut niveau.
Elle inclut un systme de ressource portable, un gestion-
naire dvnements, le support PostScript, une biblioth-
que de composants graphiques trs complte (dont un
grant les diagrammes de Gantt), des outils de conception
dIHM interactifs trs puissants (avec gestion dtat), des
composants grant la connexion et lutilisation de bases de
donnes (Oracle, IBM DB2, etc.)
La rputation de cette bibliothque nest plus faire.
Utilitaires
Understand for C++ Reverse engineering,
documentation and metrics tool
Site : http://www.scitools.com/products/understand
Licence : Commerciale
Systmes : Windows, Linux, Solaris, HP-UX, IRIX, plug-
in pour Eclipse
Langages : C, C++. Il existe aussi des versions pour C# et
Java
Understand for C++ est un outil danalyse, de documen-
tation et de mtrique (mesure) de code source. Il permet
de naviguer dans le code grce un systme de rfrences
croises, dditer le code (affch avec mise en forme), et
de le visualiser sous diverses vues graphiques.
888
Cet environnement inclut des API PERL et C permettant
dinclure votre propre systme de documentation de votre
code source.
Cet outil, diffcile dutilisation au premier abord, justife
leffort dapprentissage par ses qualits.
Ch C/C++ interpreter quand le C/C++ devient script
Site : http://www.softintegration.com
Licence : Commerciale, une version gratuite existe (mais
elle nest pas embarquable)
Systmes : Windows, Linux, Mac OS X, Solaris, HP-UX,
FreeBSD et QNX
Compilateurs : GCC, HP C++, Sun CC, Visual C++
Ch est linterprteur C/C++ le plus complet. Il peut tre
embarqu dans vos applications. Il supporte la norme
ISO C (C90), la plupart des nouvelles fonctionnalits
apportes par le C99, les classes en C++, POSIX, X/
Motif, Windows, OpenGL, ODBC, GTK+, C LAPACK,
CGI, XML, le dessin graphique 2D/3D, le calcul numri-
que avanc et la programmation en shell. De plus, Ch pos-
sde quelques autres fonctionnalits que lon retrouve
dans dautres langages et logiciels.
Ch Standard Edition est gratuit, mme pour des applica-
tions commerciales. Dommage que la version embarqua-
ble (Embedded Ch) ne le soit pas, mme pour les projets
non commerciaux
uI|Iarcs
Annexe B
Lcs a|ouIs dc |a
fuIurc normc
L++ (L++0x)
C++0x, la future norme du langage C++, remplacera
lactuelle norme C++ (ISO/IEC 14882), plus connue sous
les acronymes C++98 et C++03, publie en 1998 et mise
jour en 2003. Celle-ci inclura non seulement plusieurs
ajouts au langage lui-mme, mais tendra galement la biblio-
thque standard C++ en lui incorporant une bonne partie
des rapports techniques C++ numro 1 (les fameux TR1).
Cette norme nest pas encore publie, mais cette annexe
en prsente quelques extraits issus du rapport N2597 datant
de mai 2008. Vous pourrez ainsi vous familiariser avec
quelques-unes des avances majeures du C++.
g++ a dj commenc implmenter certaines parties de
cette future norme. Vous pouvez vous rfrer ladresse
web http://gcc.gnu.org/projects/cxx0x.html pour
en suivre la progression. Les autres acteurs du secteur des
compilateurs (Intel, Borland, etc.) attendent certainement
que cette norme soit fge pour fnir (ou commencer) leur
propre implmentation. Il faudra donc attendre encore
avant de pouvoir en utiliser tout le potentiel
888 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Variable locale un thread
thread_local
En environnement multithread, chaque thread possde
souvent ses propres variables. Cest le cas par exemple des
variables locales dune fonction, mais pas des variables glo-
bales ou statiques.
Un nouveau type de stockage, en plus des nombreux exis-
tants (extern, static, register et mutable) a t propos
pour le prochain standard : le stockage local au thread. Le
nouveau mot-cl correspondant est thread_local.
Un objet thread est analogue un objet global. Les objets
globaux existent durant toute lexcution dun programme
tandis que les objets thread existent durant la vie du thread.
la fn du thread, les objets thread sont inaccessibles.
Comme pour les objets statiques, un objet thread peut tre
initialis par un constructeur et dtruit avec un destructeur.
Unicode et chanes littrales
char s[] = Chaine ASCII standard;
wchar_t s[] = LChaine wide-char ;
char s[] = u8chaine UTF-8;
char16_t s[] = uChaine UTF-16;
char32_t s[] = UChaine UTF-32;
Le C++ actuel offre deux types de chanes littrales. La pre-
mire, compose entre guillemets, permet de coder des cha-
nes de caractres ASCII zro terminal. La deuxime (L)
permet de le faire avec un jeu de caractres large (wchar_t).
Aucun de ces deux types ne supporte les chanes Unicode.
881
Linternationalisation des applications devenant la norme
aujourdhui, le C++0x permettra au langage de supporter
Unicode, laide de trois encodages : UTF-8, UTF-16 et
UTF-32. De plus, deux autres types de caractres feront
leur apparition : char16_t et char32_t. Vous laurez com-
pris, ils permettront le support de UTF-16 et UTF-32.
UTF-8 sera trait directement avec le type char.
Lcriture de chanes littrales utilise souvent les squences
dchappement pour prciser certains caractres, comme
par exemple \x3F. Les chanes Unicode possdent aussi
leur squence dchappement. La syntaxe est illustre dans
lexemple suivant :
u8caractre Unicode : \u2018.;
ucaractre Unicode : \u2018.;
Ucaractre Unicode : \u2018.;
Le nombre aprs \u est donn sous forme hexadcimale.
Il ne ncessite pas la prsence du prfxe 0x. Si vous utilisez
\u, il est sous-entendu quil sagit dun caractre Unicode
16 bits. Pour spcifer un caractre Unicode 32 bits, utili-
sez \U et une valeur hexadcimale 32 bits. Seules des valeurs
Unicode valides sont autorises. Par exemple, des valeurs
entre U+D800 et U+DFFF sont interdites car elles sont
rserves aux paires de substitution en encodage UTF-16.
R[Une chaine \ bas niveau avec ce quon veut ];
Rdelimiteur[Encore \ ce quon veut ]delimiteur;
Il est parfois utile de dsactiver les squences dchappe-
ment. C++0x fournit un moyen de coder des chanes
bas niveau . Dans la premire ligne de lexemple prc-
dent, tout ce qui est entre les crochets ([ et ]) fait partie
de la chane. Dans la deuxime ligne, delimiteur[ marque
le dbut de la chane et ]delimiteur en marque la fn.
uncodc cI chancs |IIcra|cs
888 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Le delimiteur est arbitraire et peut tre dfni votre
convenance ; il doit simplement tre le mme au dbut et
la fn.
Comme le montre lexemple suivant, les chanes bas niveau
sont galement disponibles en Unicode :
u8RXXX[une chaine UTF-8 bas niveau.]XXX;
uR*@[une chaine UTF-16 bas niveau.]*@;
UR[une chaine UTF-32 bas niveau.];
Dlgation de construction
class UnType
{
int nombre ;
public :
UnType(int unNombre) : nombre(unNombre) { }
UnType() : UnType(42) { }
};
Les classes sont un lment essentiel du C++. Les change-
ments apports par la norme C++0x faciliteront et scu-
riseront la mise en uvre dune hirarchie de classes.
En C++ standard, un constructeur ne peut pas en appeler
un autre : chaque constructeur doit construire tous les
membres de la classe lui-mme, ce qui implique souvent
de dupliquer le code dinitialisation. Grce au C++0x, un
constructeur pourra en appeler dautres. Dautres langages,
comme Java, utilisent dj ce mcanisme (connu sous le
nom de dlgation ) pour rutiliser le comportement
dun constructeur existant.
880
AIIcnIon
C++03 autorisera la syntaxe suivante pour linitialisation des
membres :
class MaClasse
{
public:
MaClasse() {}
explicit MaClasse(int i) : m_i(i) {}
private:
int m_i = 10;
};
Tout constructeur initialisera m_i avec la valeur 10, sauf si ce
constructeur surcharge linitialisation de m_i avec sa propre
valeur. Ainsi, le constructeur vide de lexemple prcdent uti-
lise linitialisation de la dfnition, mais lautre constructeur
initialise la variable avec la valeur donne en paramtre.
Hritage des constructeurs
class B : A
{
using A::A;
// ...
};
On aimerait souvent pouvoir initialiser une classe drive
avec le mme ensemble de constructeurs que la classe de
base. Jusqu prsent, la seule manire de faire cela consiste
redclarer tous les constructeurs en les redirigeant sur
ceux de la classe de base. Si le compilateur pouvait faire le
travail, il en rsulterait moins derreur et lintention serait
rendue bien visible. La nouvelle norme C++ va tendre la
signifcation du mot-cl using en ce sens. Il acquiert ainsi
une nouvelle signifcation : permettre dhriter tous les
hcrIagc dcs consIrucIcurs
800 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
constructeurs dune classe mre donne, vitant ainsi davoir
tous les coder de nouveau.
struct B1
{
B1( int );
};

struct B2
{
B2( int = 13, int = 42 );
};

struct D1 : B1
{
using B1::B1;
};

struct D2 : B2
{
using B2::B2;
};
Dans lexemple prcdent, les constructeurs de B1 candi-
dats lhritage pour D1 sont :
B1( const B1 & ) ;
B1( int ).
Lensemble des constructeurs de D1 est :
D1() constructeur par dfaut implicite, mal form si uti-
lis ;
D1( const D1 & ) constructeur par copie implicite, non
hrit ;
D1( int ) constructeur hrit implicitement.
Les constructeurs de B2 candidats lhritage pour D2 sont :
B2( const B2 & ) ;
B2( int = 13, int = 42 ) ;
B2( int = 13 ) ;
B2().
801
Lensemble des constructeurs de D2 est :
D2() constructeur par dfaut implicite, non hrit ;
D2( const D2 & ) constructeur par copie implicite, non
hrit ;
D2( int, int ) constructeur hrit implicitement ;
D2( int ) constructeur hrit implicitement.
Info
Si deux dclarations using hritent de constructeurs ayant la
mme signature, le programme est mal form ; il est alors
ncessaire de le surcharger dans la classe flle.
struct B1
{
B1( int );
};

struct B2
{
B2( int );
};
struct D1 : B1, B2
{
using B1::B1;
using B2::B2; // mal form: double dclaration
// implicite dun mme constructeur
};

struct D2 : B1, B2
{
using B1::B1;
using B2::B2;
D2( int ); // ok : dclaration utilisateur
// prvient le confit
};

hcrIagc dcs consIrucIcurs
802 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Constructeur et destructeur
par dfaut
struct Type
{
Type() = default;
};
struct Type
{
Type() = delete;
};
En C++ standard, le compilateur peut fournir, pour les
objets qui ne les fournissent pas explicitement, un construc-
teur par dfaut, un constructeur par copie, un oprateur de
copie (operator=) et un destructeur. Le C++ dfnit gale-
ment des oprateurs globaux (comme operator= et opera-
tor new) qui peuvent galement tre surchargs.
Le problme est quil ny a aucun moyen de contrler la
cration de ces versions par dfaut. Par exemple, pour
rendre une classe non copiable, il faut dclarer le construc-
teur par dfaut et loprateur de copie en tant que mem-
bres privs et ne pas les implmenter. De cette faon,
lutilisation de ces fonctions provoquera soit une erreur de
compilation, soit une erreur ddition de liens. Cette tech-
nique, si elle fonctionne, est toutefois loin dtre idale.
C++0x permettra de forcer, ou empcher, la gnration
de fonctions par dfaut. Le code suivant dclare explicite-
ment le constructeur par dfaut dun objet :
struct Type
{
Type() = default; // dclaration explicite
Type(AutreType valeur);
};
808
Inversement, il est possible de dsactiver la gnration
automatique de ces fonctions. Le code suivant montre
comment crer un type non copiable :
struct Type // non copiable
{
Type() = default;
Type(const Type&) = delete;
Type& operator=(const Type&) = delete;
};
Le code suivant montre comment empcher un type
dtre allou dynamiquement. La seule faon dallouer un
tel objet est de crer une variable temporaire (allocation
sur la pile). Il est impossible dcrire Type *ptr = new Type ;
(allocation sur le tas).
struct Type // allocation dynamique interdite
{
void* operator new(std::size_t) = delete;
};
La spcifcation = delete peut tre utilise sur nimporte
quelle fonction membre pour empcher son utilisation.
Cela peut tre utile, par exemple, pour empcher lappel
dune fonction avec certains paramtres. Lexemple suivant
montre comment empcher une conversion implicite de
double vers int lors de lappel de la fonction membre f()
avec un nombre rel. Un appel tel obj->f(1.0) provoquera
une erreur de compilation.
struct Type // pas de double
{
void f(int i);
void f(double) = delete;
};
LonsIrucIcur cI dcsIrucIcur par dcfauI
804 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
La technique employe dans lexemple prcdent peut
tre gnralise pour forcer le programmeur nutiliser
que le type explicitement dfni par la dclaration de la
fonction membre. Le code suivant nautorise des appels
la fonction membre f() quavec le type int :
struct Type // que des int
{
void f(int i);
template<T> void f(T) = delete;
};
union tendue
struct Point
{
Point() {}
Point(int x, int y) : m_x(x), m_y(y) {}
int m_x, m_y;
};
union
{
int i;
double d;
Point p; // autoris avec C++0x
};
En C++, le type des membres dune union est soumis
certaines restrictions. Par exemple, les unions ne peuvent
pas contenir des objets dfnissant des constructeurs non
triviaux. Plusieurs des limitations imposes sur les unions
semblant tre superfues, le prochain standard enlvera
toutes les restrictions sur le type des membres des unions
lexception des rfrences sur les types. Cela rendra les
unions plus faciles utiliser.
805
Oprateurs de conversion
explicites
struct Type
{
explicit operator bool() { ... }
};
La nouvelle norme permettra dappliquer le mot-cl expli-
cit tout oprateur de conversion, en plus des constructeurs,
interdisant au compilateur de convertir automatiquement
un type en un autre. Le cas ci-dessus empchera par exem-
ple la conversion implicite en boolen.
Type numration fort
enum class Enumeration
{
Val1,
Val2,
Val3 = 10,
Val4 // 11
};
Les numrations sont par nature des nontypes : ils ont
lapparence dun type (et presque la signifcation) mais
nen sont pas rellement. Ce sont en effet de simples
entiers. Cela permet de comparer deux valeurs provenant
dnumrations distinctes. La dernire norme (datant de
2003) a apport un peu de scurit en empchant la
conversion dun entier en numration ou dune num-
ration vers une autre. Autre limitation : le type dentier
sous-jacent ne peut tre confgur ; il est dpendant de
limplmentation du compilateur et de la plate-forme.
Jypc cnumcraIon forI
808 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
La norme C++0x permettra, en ajoutant le mot-cl class
aprs enum, de crer de vrais types numration part
entire. Ainsi avec lexemple gnrique ci-avant, une com-
paraison du type Val4 == 11 gnrera une erreur de compi-
lation.
Par dfaut, le type sous-jacent dune classe dnumration
est toujours le type int. Il pourra nanmoins tre person-
nalis. Dans lexemple ci-aprs, vous voyez comment le
changer en unsigned int ou long. De plus, il sera ncessaire
de prciser le nom de lnumration : Enum1::Val1.
enum class Enum1 : unsigned int { Val1, Val2 };
enum class Enum2 : long { Val1, Val2 };
Listes dinitialisation
class Sequence
{
public:
Sequence(std::initializer_list<int> list);
};
Sequence s = { 1, 2, 3, 5, 7, 0 };
void Fonction(std::initializer_list<foat> list);
Fonction({1.0f, -3.45f, -0.4f});
Le concept de liste dinitialisation existe dj en C. Lide
est de fournir une liste darguments pour initialiser un
tableau ou une structure (dans ce dernier cas, les lments
doivent tre donns dans le mme ordre que ceux de la
structure). Le systme est rcursif et permet dinitialiser
des structures de structures. C++0x tend ce concept aux
classes. Le concept de liste dinitialisation se nomme std::
801
initializer_list<>. Il pourra tre utilis non seulement
avec les constructeurs mais aussi avec les fonctions.
Une liste dinitialisation est constante. Ses valeurs ne peu-
vent pas tre changes ou modifes par la suite.
Les conteneurs standard pourront tre initialiss grce
cette nouvelle fonctionnalit.
std::vector<std::string> v = { abc, defgh, azerty };
Initialisation uniformise
struct Structure
{
int x;
foat y;
};

struct Classe
{
Classe(int x, foat y) : m_x(x), m_y(y) {}
private:
int m_x;
foat m_y;
};
Structure var1{5, 3.2f};
Classe var2{2, 4.3f};
C++0x met en place une uniformisation de linitialisation
des types. Linitialisation de var1 fonctionne exactement
comme une liste dinitialisation de style C (mais le = nest
plus ncessaire). Une conversion implicite est automati-
quement utilise si ncessaire (et si possible), sinon il en
rsulte une erreur de compilation. Linitialisation de var2
appelle simplement le destructeur.
InIa|saIon unformscc
808 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Cette uniformisation va permettre domettre le type dans
certains cas. Le code suivant vous montre en quel sens :
struct StrindAndID
{
std::string text;
int id;
};
StringAndID makeDefault()
{
return {UnTexte, 12}; // Notez lomission du type
}
Cette uniformisation ne remplace pas la syntaxe habituelle
des constructeurs. En effet, il peut tre indispensable dy
avoir recours. Imaginez quune classe implmente un
constructeur par liste dinitialisation (Classe(std::initia-
lizer_list<T>);). Ce constructeur aura priorit sur tous
les autres avec la syntaxe unife. On rencontre ce cas de
fgure avec la nouvelle implmentation de la STL, comme
par exemple std::vector<>. Cela implique que lexemple
suivant ne cre pas un tableau de quatre lments mais un
tableau contenant 4 pour seul lment :
std::vector<int> V{4}; // V contient la valeur 4
Pour crer un vecteur de quatre lments, il faut utiliser la
syntaxe de constructeur standard, comme ceci :
std::vector<int> V(4); // V contient 4 lments vides
800
Type automatique
auto variable = ...;
decltype(variable)
Jusqu prsent, pour dclarer une variable en C++, il tait
obligatoire de spcifer son type. Cependant, avec larrive
des templates et des techniques de mtaprogrammation
associes, le type de quelque chose nest pas toujours ais
dfnir. Cest particulirement le cas des valeurs de retour
des fonctions templates. De mme, il est parfois pnible de
dterminer le type de certaines variables que lon souhaite
sauvegarder, obligeant fouiller parfois loin dans les df-
nitions de classes.
Grce au mot-cl auto, C++0x permettra la dclaration
dune variable sans en connatre le type, condition toutefois
dinitialiser celle-ci explicitement. Le type est ainsi spcif
implicitement par la valeur dinitialisation. Le code suivant
illustre cette technique avec lappel dune fonction (le
compilateur connat forcment son type de retour) et avec
une constante littrale (en loccurrence un int).
auto varDeTypeObscure = std::bind(&uneFonction, _2,

_1, unObjet);
auto varEntiere = 5;
C++0x offrira encore un mot-cl supplmentaire, decl-
type(...), permettant dobtenir le type dune variable, et
surtout de pouvoir lutiliser comme un type traditionnel.
int unEntier;
decltype(unEntier) unAutreEntier = 33;
Jypc auIomaIquc
400 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
AsIucc
Le mot-cl auto permettra aussi dobtenir un code plus ais
lire. Par exemple, le code suivant :
for (std::vector<int>::const_iterator it = V.begin();
it != V.end(); ++it)
{
// ...
}
pourra scrire :
for (auto it = V.begin(); it != V.end(); ++it)
{
// ...
}

Boucle for ensembliste
int tableau[5] = {1, 2, 3, 4, 5};
for(int &x : tableau)
{
x *= 2;
}
La bibliothque BOOST dfnie la notion dintervalle
(range). Les conteneurs ordonns sont un surensemble de
la notion dintervalle, et deux itrateurs sur un tel conte-
neur peuvent dfnir un intervalle. Ces concepts, et les
algorithmes qui les utilisent, seront inclus dans la biblio-
thque C++0x standard. Cependant, lintrt du concept
dintervalle est tel que le C++0x en fournira une impl-
mentation au niveau du langage lui-mme.
Dans lexemple prcdent, la variable x a une porte gale
celle de la boucle for. La partie aprs de : est un intervalle
401
sur lequel seffectue litration. Les tableaux de type C
sont automatiquement convertis en intervalle. Tout objet
respectant le concept dintervalle peut y tre utilis. Les
std::vector<> de la STL du C++0x en sont un exemple.
Syntaxe de fonction unife
[] Fonction(paramtres) -> TypeRetour;
La syntaxe laquelle nous sommes habitus jusqu pr-
sent, issue du C, commenait faire sentir ses limites. Par
exemple, il est actuellement impossible dcrire le code
suivant :
template <typename A, typename B>
T plus(const A& a, const B& b)
{
return a+b;
}
On pourrait tre tent dutiliser la nouvelle fonctionnalit
de type automatique que le C++0x fournira, en rempla-
ant T par decltype(A+B). Mais cela ne sufft pas, car il fau-
drait que les types A et B soient dfnis, et cela nest vrai
quaprs linterprtation du prototype de la fonction. Do
lajout la norme C++0x dune nouvelle syntaxe de
fonction unife. Le code suivant montre comment crire
une telle fonction en C++0x :
template <typename A, typename B>
[] plus(const A& a, const B& b) -> decltype(a+b)
{
return a+b;
}
SynIaxc dc foncIon uncc
402 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Pour les fonctions membres, cette syntaxe sutilise ainsi :
struct Structure
{
[]FonctionMembre(int x) -> int;
};
[] Structure::FonctionMembre(int x) -> int
{
return x + 2;
}
Concepts
concept NomDuConcept<typename T> { ... }
auto concept NomDuConcept<typename T> { ... }
template <typename T> requires NomDUnConcept<T> ...
concept_map NomDuConcept<Type> { ... }
template<typename T> concept_map NomDuConcept<T> { ... }
Lcriture de classes et de fonctions templates ncessite
presque obligatoirement de prsupposer certaines condi-
tions sur les paramtres templates. Par exemple, la STL
actuelle suppose que les types utiliss avec ses conteneurs
soient assignables. Contrairement au contrle de type inh-
rent au polymorphisme, il est possible de passer nimporte
quel type comme paramtre template, condition bien sr
quil supporte toutes les oprations employes dans limpl-
mentation de ce template. Du coup, les prrequis sur le
type du paramtre sont implicites au lieu dtre explicites.
Les concepts vont permettre de codifer linterface quun
paramtre template ncessite.
408
La premire motivation la cration des concepts est lam-
lioration des messages derreur du compilateur. En effet,
jusqu prsent, une erreur lie un manque de fonctionna-
lit dun paramtre template provoquait un message derreur
souvent trs long (le type template est souvent trs long). De
plus, ce message survient bien plus loin dans le code quau
moment de linstanciation de la classe ou de la fonction
template (au moment de lutilisation de la fonctionnalit
manquante), rendant diffcile la localisation et la compr-
hension de lerreur.
template <LessThanComparable T>
const T& min(const T& x, const T& y)
{
return y < x ? : y : x;
}
La fonction template suivante, en employant LessThanCompara-
ble plutt que class ou typename, exprime comme prrequis
que le type T doit respecter le concept LessThanComparable
prcdemment dfni. Grce cela, si vous utilisez cette fonc-
tion template avec un type qui ne respecte pas ce concept,
vous obtiendrez un message derreur clair indiquant que le
type utilis lors de linstanciation du template ne respecte
pas le concept LessThanComparable. Le code suivant est une
forme dcriture plus gnrique exprimant la mme chose,
mais permettant aussi de spcifer plusieurs concepts au
lieu dun :
template <typename T> requires LessThanComparable<T>
const T& min(const T& x, const T& y)
{
return y < x ? : y : x;
}
LonccpIs
404 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Chose intressante, il sera possible dempcher lutilisation
dun modle template avec un type conforme un concept
donn. Par exemple, requires ! LessThanComparable<T> :
auto concept LessThanComparable<typename T>
{
bool operator<(T, T);
}
Le mot-cl auto signife ici que tout type qui supporte les
oprations mentionnes dans le concept est considr
comme supportant le concept. Sans ce mot-cl, le type
doit utiliser une carte de concept pour signifer lui-mme
quil supporte ce concept. Le concept prcdent indique
que tout type T tel quil existe un oprateur < prenant
deux objets de type T et retournant un bool sera considr
comme LessThanComparable. Cet oprateur ne doit pas
ncessairement tre un oprateur global mais peut aussi
tre un oprateur membre du type T.
auto concept Convertible<typename T, typename U>
{
operator U(const T&);
}
Les concepts peuvent impliquer plusieurs types diffrents.
Par exemple, le concept prcdent exprime quun type
peut tre converti en un autre. Pour utiliser un tel concept,
il est obligatoire dutiliser la syntaxe gnralise :
template<typename U, typename T> requires Convertible<T, U>
U convert(const T& t)
{
return t;
}
405
Les concepts peuvent aussi tre composs. La dfnition du
concept suivant indique quil doit aussi satisfaire un autre
concept, Regular, prcdemment dfni :
concept InputIterator<typename Iter, typename Value>
{
requires Regular<Iter>;
Value operator*(const Iter&);
Iter& operator++(Iter&);
Iter operator++(Iter&, int);
}
Les concepts peuvent galement tre drivs dun autre
concept, comme avec lhritage. Voici un exemple de syn-
taxe :
concept ForwardIterator<typename Iter, typename Value> :
InputIterator<Iter, Value>
{
// Autres contraintes
}
Des typenames peuvent aussi tre associs un concept. Cela
impose au template respectant ce concept de dfnir ces types.
Le code suivant illustre cela avec le concept ditrateur :
concept InputIterator<typename Iter>
{
typename value_type;
typename reference;
typename pointer;
typename difference_type;
requires Regular<Iter>;
requires Convertible<reference, value_type>;
reference operator*(const Iter&); // drfrencement
Iter& operator++(Iter&); // pr-incrment
Iter operator++(Iter&, int); // post-incrment
// ...
}
LonccpIs
408 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Les cartes de concept, que nous avons voques prc-
demment, permettent dassocier explicitement un type
un concept. Lexemple suivant permet de spcifer tous les
types du concept dInputIterator pour le type char* :
concept_map InputIterator<char*>
{
typedef char value_type ;
typedef char& reference ;
typedef char* pointer ;
typedef std::ptrdiff_t difference_type ;
};
Les cartes de concept peuvent elles-mmes bnfcier de
la notion de template. Lexemple suivant gnralise la carte
de concept prcdente tous les pointeurs :
template <typename T>
concept_map InputIterator<T*>
{
typedef T value_type ;
typedef T& reference ;
typedef T* pointer ;
typedef std::ptrdiff_t difference_type ;
};
Autorisation de sizeof
sur des membres
struct UnType { AutreType membre; };
sizeof(UnType::membre);
Avec la norme actuelle, cet exemple produit une erreur de
compilation. Avec la norme C++0x, vous obtiendrez la
taille de AutreType.
401 Jcmp|aIc cxIcrnc
Amlioration de la syntaxe
pour lutilisation des templates
Type<Autre<int>> obj;
Jusqu aujourdhui, les compilateurs confondent >> avec
loprateur de redirection. Il est obligatoire de sparer les
deux > par un (ou plusieurs) espace. Cette limitation sera
leve avec lapparition du support de C++0x.
Template externe
extern template class ...;
En C++, le compilateur doit instancier un template
chaque fois que celui-ci est rencontr. Cela peut consid-
rablement augmenter le temps de compilation, en particu-
lier si le template est instanci dans de nombreux fchiers
avec les mmes paramtres. Il nexiste aucun moyen de
dire de ne pas provoquer linstanciation dun template.
Le C++ dispose dj dun moyen de forcer linstanciation
dun template. Le code suivant en montre un exemple :
template class std::vector<MaClasse>;
C++0x introduit lide de template externe, permettant
ainsi de prvenir son instanciation. Le code suivant montre
comment, en indiquant au compilateur de ne pas instan-
cier le template dans cette unit de traduction :
extern template class std::vector<MaClasse>;
408 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Expressions constantes gnralises
constexpr
Le C++ dispose dj du concept dexpression constante.
Cest le cas par exemple de 3 + 4 qui correspond toujours au
mme rsultat. Les expressions constantes sont des opportu-
nits doptimisation pour le compilateur. Il excute lexpres-
sion la compilation et stocke le rsultat dans le programme.
Dun autre ct, il y existe un certain nombre dendroits o
les spcifcations du langage C++ requirent des expressions
constantes : dfnir un tableau ncessite une constante, et une
valeur dnumration doit tre une constante.
Pourtant, alors quune expression constante est toujours le
rsultat dun appel de fonction ou dun constructeur, il est
impossible dcrire (actuellement) le code ci-aprs. Ce
nest pas possible car cinq() + 5 nest pas une expression
constante. Le compilateur na aucun moyen de savoir que
cinq() est une constante.
int cinq() { return 5; }
int tableau[cinq() + 5]; // illgal
C++0x introduit le mot-cl constexpr, qui permet au
programmeur de signifer quune fonction ou un objet est
une constante la compilation. Lexemple prcdant peut-
tre rcrit comme ci-aprs. Cela permet au compilateur
de comprendre, et vrifer, que cinq() est une constante.
constexpr int cinq() { return 5; }
int tableau[cinq() + 5]; // ok : cre un tableau de

10 entiers
Lutilisation de constexpr sur une fonction impose des
limitations trs strictes sur ce que la fonction peut faire.
400
Premirement, la fonction ne peut pas retourner void.
Deuximement, le contenu de la fonction doit tre de la
forme return expression. Troisimement, expression
doit tre une expression constante, aprs substitution des
paramtres. Cette expression constante ne peut quappeler
dautres fonctions dfnies comme constpexpr, ou utiliser
dautres variables ou donnes constantes elles aussi.
Quatrimement, toute forme de rcursion est interdite.
Enfn, une fonction ainsi dclare ne peut tre appele
que dans sa porte.
Les variables peuvent aussi tre des expressions constantes.
Les variables ainsi dclares sont implicitement const. Elles
peuvent uniquement stocker des rsultats dexpressions ou
de constructeurs constants.
constexpr double graviteTerrestre = 9.8;
constexpr double graviteLunaire = graviteTerrestre / 6
Afn de pouvoir crer des objets constants, un construc-
teur peut tre dclar constexpr. Dans ce cas, son corps
doit tre vide et ses membres doivent tre initialiss avec
des expressions constantes. Le destructeur dun tel objet
doit galement tre trivial.
Tout membre dune classe, comme le constructeur par
copie, la surcharge doprateur, etc., peut tre dclar
comme constexpr, condition quil vrife les contraintes
dune fonction constante. Cela permet au compilateur de
copier des classes ou de faire des oprations sur celles-ci
pendant le processus de compilation.
Bien entendu, les fonctions et constructeurs constants peu-
vent tre appels avec des variables non constantes. Dans
ce cas, aucune optimisation ne sera faite la compilation :
le code sera appel lors de lexcution. Du coup, le rsultat ne
peut videmment pas tre stock dans une variable constante.
Lxprcssons consIanIcs gcncra|sccs
410 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Les variadic templates
template <class ... Types> ...;
Les variadic templates sont le pendant pour les templates des
fonctions variadiques, dont la plus connue est printf().
Les templates pourront ainsi recevoir un nombre indter-
min de paramtres, au sens de non fx lavance.
La premire notion connatre pour utiliser cette nou-
velle fonctionnalit est le template parameter pack. Cest le
paramtre template qui reprsente zro ou plusieurs argu-
ments. Dans la dfnition gnrique prcdente, il corres-
pond class ... Types.
La deuxime notion est le function parameter pack. Cest
lquivalent de la premire notion pour ce qui est des
paramtres dune fonction template. Dans template<class
... Types> void f(Types ... args); le function parameter
pack est Types... args.
Lexpression parameter pack dsigne indiffremment lune
ou lautre des deux notions prcdentes.
Enfn, la troisime et dernire notion est le pack expansion.
Cest une expression qui permet de transmettre une
fonction la liste des arguments du pack. Dans le code sui-
vant, &rest... est un pack expansion :
template <ckass ... Types> void f(Types ... rest);
template <ckass ... Types> void f(Types ... rest)
{
f(&rest ...);
}
Le code suivant est utilis dans la nouvelle dfnition de
tuple (n-uplet). Elle permet de rcuprer le dernier argument
411
dun pack et illustre bien lutilisation de cette nouvelle
fonctionnalit :
// rcupration du type du dernier argument
template <class... Args>
struct last;

template <class T>
struct last<T> { typedef T type; }

template <class T, class... Args>
struct last<T, Args...> : last<Args...> {};

// rcupration du dernier argument
template <class T> const T& last_arg(const T& t) {

return t; }
template <class T, class... Args>
typename last<Args...>::type const &
last_arg(const T&, const Args&... args)
{
return last_arg(args...);
}
Pointeur nul
nullptr
Depuis prs dune trentaine dannes, lcriture du poin-
teur nul est sujette polmique : NULL, 0 ou (void*)0 ? Le
C++0x va enfn clore le chapitre ; nullptr va devenir un
nouveau mot-cl dsignant le pointeur nul. Voici quelques
exemples illustrant son utilisation et son intrt.
PonIcur nu|
412 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
char* p = nullptr; // ok
char c = nullptr; // erreur de type
int i = nullptr; // erreur de type
Pointeurs et types numriques
int (A::*pmf)(char*) = nulltpr; // ok
int A::*pmi = nullptr; // ok, pointeur sur une donne

membre
Pointeurs et membres
if (nullptr == 0) // erreur de type
if (nullptr) // erreur, pas de conversion implicite

vers bool
if (p == nullptr) // ok
Pointeurs et comparaison
void f(int);
void f(char*);
f(0); // appelle f(int)
f(nullptr); // appelle f(char*)
Pointeurs et surcharge
Tuple
template <class... Types> class tuple;
Un tuple est une collection de dimension fxe dobjets de
types diffrents. Tout type dobjets peut tre lment dun
tuple. Cette nouvelle fonctionnalit est implmente dans
418
un nouveau fchier en-tte et bnfcie des extensions du
C++0x telles que : paramtres templates infnis (variadic
templates), rfrence sur rfrence et arguments par dfaut
pour les fonctions templates.
typedef tuple<int, double, long&, const char*> tuple_test;
long longueur = 43;
tuple_test essai( 22, 3.14, longueur, Bonjour);
longueur = get<0>(essai); // longueur vaudra 22
get<3>(essai) = Au revoir; // modife la 4e valeur du tuple
Il est possible de crer le tuple essai sans dfnir son
contenu si les lments du tuple possdent tous un
constructeur par dfaut. De mme, il est possible dassi-
gner un tuple un autre si les deux tuples sont de mme
type (dans ce cas, chaque lment doit possder un
constructeur par copie) ou si chaque lment de droite est
convertible avec le type de llment de gauche (grce
un constructeur appropri).
tuple <int, double, std::string> t1;
tuple <char, short, const char*> t2;
t1 = t2; // Ok car int = char et double = short possible
// et std::string(const char*) existe
Les oprateurs relationnels sont disponibles pour les tuples
ayant le mme nombre darguments. Deux expressions
sont ajoutes pour vrifer les caractristiques dun tuple
la compilation :
tuple_size<T>::value retourne le nombre dlments
du tuple T ;
tuple_element<i, T>::type retourne le type de lobjet
en position i du tuple T.
Jup|c
414 ANNLXL 8 Lcs a|ouIs dc |a fuIurc normc L++ (L++0x)
Lambda fonctions et lambda
expressions
[](paramtres){code}
Les lambda fonctions sont bien agrables pour ceux qui
utilisent les algorithmes STL, car il devient enfn possible
de les utiliser sans pour autant crire une fonction qui ne
sera utilise quune seule fois.
Par exemple, si vous voulez aujourdhui affcher le contenu
dun std:vector<> sur la console, deux possibilits soffrent
vous : la boucle classique et la fonction std::copy avec les
itrateurs de fux. Le code suivant vous rappelle celles-ci :
// lancienne
for( std::vector<Objet>::iterator it = V.begin(); it

!= V.end() +it)
std::cout << *it << ;
// avec les algorithmes STL
std::copy( V.begin(), V.end(), std::ostream_iterator

<const Objet>(cout, ) );
Grce aux lambda fonctions, vous pourrez dsormais
crire le code suivant :
for_each( V.begin(), V.end(), [](const Objet& o) {
std:cout << o << ;
});
415
Leur intrt est encore renforc lorsque cela vite de coder
des foncteurs ou des fonctions. Par exemple, le code sui-
vant montre quel point il sera simple de rechercher un
lment de conteneur respectant certains critres :
std::fnd_if( V.begin(), V.end(), [](const Objet& o) {
return w.poids() > 98;
});
En fn de compte, tous les algorithmes STL de type boucle
pourront tre utiliss comme des boucles. Le }); va devenir
un classique
Lamhda foncIons cI |amhda cxprcssons
Annexe C
LonvcnIons
dappc| x88
Les bibliothques de codes, sous forme de bibliothques
dynamiques (.DLL sous Windows, .so sous Unix/Linux)
ou de bibliothque statiques (souvent .lib sous Windows et
.a sous Unix/Linux), ne sont pas toutes crites en C ou
C++. Cest pourquoi vous rencontrerez certainement des
mots-cls tels que stdcall, safecall, cdecl ou WINAPI (ce
dernier est en fait une macro dclare par les API Windows).
Ils correspondent des conventions dappel et dfnissent
comment appeler des fonctions souvent compiles spa-
rment, peut-tre mme laide dun compilateur diffrent
du vtre au moment de lexcution du programme.
Une convention dappel dtermine :
lordre dans lequel les paramtres sont transmis la
fonction ;
o les paramtres sont placs (dans la pile ou dans des
registres) ;
quels registres peuvent tre utiliss par la fonction ;
qui de lappel (la fonction) ou de lappelant (la partie
de code qui lappelle) doit nettoyer la pile aprs lappel.
Un sujet li la convention dappel est la dcoration de nom
(ou name mangling). Elle dtermine comment lier les noms
utiliss dans le code avec les symboles de noms utiliss par
418 ANNLXL L LonvcnIons dappc| x88
le lieur (linker) en ajoutant automatiquement le nombre et
le type des paramtres associs au nom dune mthode.
Si vous voulez en savoir un peu plus sur larchitecture
x86, nhsitez pas aller jeter un il sur cette page web :
http://en.wikipedia.org/wiki/X86.
Info
Il existe souvent de subtiles diffrences dans lapplication de
ces conventions par les divers compilateurs en usage. Il est
donc souvent ardu dinterfacer des codes compils par des
compilateurs diffrents. Heureusement, les conventions utili-
ses pour les API standard (comme stdcall) sont implmen-
tes de manire uniforme.
Microprocesseurs Intel *
Fam||c Proccsscurs
40xx, 80xx et 80xx 4004, 4040, 8080, 8085, 8086, 8088, 80186, 80188,
80286, 80386, 80486, 486SL, 486SX, 486DX
Pentium Pentium, Pentium MMX
P6 Pentium Pro, Pentium II, Pentium III
NetBurst Pentium 4, Pentium 4-M, Pentium D, Pentium
Extreme Edition
Mobile Architecture Pentium M, Core Solo et Duo
Core Architecture Core 2 Solo, Duo et Quad, Core 2 Extreme
Nehalem Core i7
Serveur / Calculateur Xeon, Itanium, Itanium 2
Autres Atom, Celeron, Centrino, Pentium Dual-Core
XScale PXA250, PXA255, PXA260, PXA270, PXA290
RISC iAPX 432, i860, i960
* Processeurs non x86 en italiques
410
Microprocesseurs AMD
Fam||c Proccsscurs
Architecture K5, K6, K7, K8, K8L, K10
Socket Socket 7, Socket Super 7, Socket A, Socket 563,
Socket S1, Socket 754, Socket 939, Socket 940,
Socket AM2, Socket AM2+, Socket F, Socket F+,
Socket AM3
Processeurs
antrieurs K7
Am2900, AMD 29000, 8086, 8088, 80286,
Am286, Am386, Am486, Am5x86, SSA5, 5k86,
AMD K6, AMD K6-2, AMD K6-III
Athlon Athlon, Athlon XP,Athlon 64, Athlon64 X2,
Athlon FX
Phenom Phenom 8000, Phenom 9000, Phenom FX
Duron / Sempron Duron, Sempron
Mobile Mobile Athlon XP, Mobile Athlon 64, Turion 64,
Turion 64 X2, Turion 64 Ultra
Serveur Athlon MP, Opteron
Autres Geode, Alchemy
Chipset ATI, AMD
Convention dappel cdecl
void __cdecl f(foat a, char b);

// Borland et

Microsoft
void __attribute__((cdecl)) f(foat a, char b);

// GNU GCC
Convention dappel par dfaut en C, elle lest aussi en
C++. Lappelant est responsable du dsempilement des
arguments, permettant ainsi dutiliser des fonctions
nombre darguments dynamiques (dfnies laide des
points de suspension ...).
LonvcnIon dappc| cdecl
420 ANNLXL L LonvcnIons dappc| x88
Les paramtres de la fonction concerne sont placs sur
la pile de droite gauche (dans lordre inverse de celui de
la dclaration de la fonction). La valeur de retour est place
dans le registre EAX, sauf pour les valeurs fottantes qui se
trouveront dans le registre fottant FP0. Les registres EAX,
ECX et EDX sont libres dtre utiliss par la fonction. La
fonction appelante nettoie la pile aprs le retour de lappel.
Il existe quelques diffrences dans limplmentation de
cdecl, notamment vis--vis de la valeur de retour. Du
coup, des programmes compils pour diffrents systmes
dexploitation et/ou par diffrents compilateurs peuvent
tre incompatibles, mme sils utilisent la convention cdecl
et ne font pas appel lenvironnement sous-jacent.
Microsoft C++ sous Windows retournera les structures de
donnes simples de moins de 8 octets dans EAX:EDX.
Les plus grandes structures ou celles ncessitant un traite-
ment particulier li aux exceptions (tels un constructeur,
un destructeur ou un oprateur daffectation particulier)
sont retournes en mmoire.
G++ sous Linux transmet toutes les structures ou classes en
mmoire, quelle que soit leur taille. En outre, les classes qui
ont un destructeur sont toujours passes par rfrence,
mme pour les paramtres par valeur. Pour ce faire, lappe-
lant alloue la mmoire ncessaire et utilise un pointeur
sur celle-ci comme premier paramtre cach. Lappel la
remplit et retourne ce pointeur tout en supprimant le
paramtre cach.
421
Convention dappel pascal
void __pascal f(foat a, char b);
// Borland et Microsoft
Les paramtres sont placs sur la pile de la gauche vers la
droite, loppos de cdecl, et lappel est responsable du
nettoyage de la pile.
Dans notre cas, lappel f(5,d); correspondrait au code
assembleur suivant :
PUSH EBP
MOV EBP, ESP
PUSH $00000005
PUSH d
CALL f
AsIucc
Que faire si votre compilateur ne supporte pas cette directive
et que vous deviez employer une bibliothque utilisant la
convention pascal ? Vous pouvez ruser en dclarant les en-ttes
des fonctions qui vous intressent en stdcall mais en inver-
sant les paramtres. Par exemple, avec gcc :
// int __pascal f(int a, int b, int c);
int __attribute__((stdcall)) f(int c, int b, int a);

LonvcnIon dappc| pascal
422 ANNLXL L LonvcnIons dappc| x88
Convention dappel stdcall
void __stdcall f(foat a, char b);
// Borland et Microsoft
void __attribute__((stdcall)) f(foat a, char b);

// GNU GCC
Cette convention est une variante de la convention pascal
dans laquelle les paramtres sont passs par la pile, de droite
gauche. Les registres EAX, ECX et EDX sont rservs
lusage de la fonction. La valeur de retour se trouve dans le
registre EAX.
Convention dappel fastcall
void __fastcall f(foat a, char b);
// Borland et Microsoft
void __attribute__((fastcall)) f(foat a, char b);

// GNU GCC
Cette convention nest pas toujours quivalente suivant
les compilateurs. Utilisez-la avec prcaution.
Les deux premiers (parfois plus) arguments 32 bits sont
transmis la fonction dans des registres : le plus souvent
dans EDX, EAX et ECX. Les autres arguments sont trans-
mis par la pile, en ordre inverse (de droite gauche)
comme cdecl. La fonction appelante est responsable du
nettoyage de la pile sil y a lieu.
428
AIIcnIon
En raison de lambigut induite par les diffrentes implmenta-
tions de cette convention, il est recommand dutiliser fastcall
uniquement pour les fonctions ayant 1, 2 ou 3 (selon le compi-
lateur) arguments 32 bits et lorsque la vitesse dexcution est
essentielle.
Convention dappel thiscall
thiscall
Cette convention est utilise par les fonctions membres
non statiques. Deux versions de thiscall se ctoient en
fonction du compilateur et de lutilisation du systme de
nombre darguments variable.
Avec GCC, thiscall est pratiquement identique cdecl :
la fonction appelante nettoie la pile, et les paramtres sont
passs de droite gauche. La diffrence tient dans lajout
du pointeur this, ajout en dernier la pile comme si
ctait le premier argument de la fonction.
Avec Microsoft Visual C++, le pointeur this est transmis
par le registre ECX et cest lappel qui nettoie la pile,
linstar de la convention stdcall utilise en C pour ce
compilateur et de lAPI Windows. Si la fonction utilise la
syntaxe des paramtres variables, cest lappelant de
nettoyer la pile (comme pour cdecl).
LonvcnIon dappc| thiscall
424 ANNLXL L LonvcnIons dappc| x88
Conventions dappel x86
MoI-c|c 0rdrcjNcIIoyagc cmarquc
cdecl DG/Appelant Souvent la convention par dfaut
pascal GD/Appel Convention OS/2 16 bits,
Windows 3.x et certaines versions
de Borland Delphi
stdcall DG/Appel Convention de lAPI Win32
fastcall DG/Appel/GCC
DG/Appel/MSVC
GD/Appel/Borland
DG/Appel/Watcom
2 registres (ECX et EDX)
avec __msfastcall
2 registres (ECX et EDX)
avec __fastcall
3 registres (EAX, EDX et ECX)
jusqu 4 registres (EAX, EDX, EBX
et ECX) en ligne de commande (voir
http://www.openwatcom.org/
index.php/Calling_Conventions#
Specifying_Calling_Conventions_
the_Watcom_Way)
thiscall DG/Appelant/GCC
DG/Appel/MSVC versions 2005 ou suprieurs
Conventions dappel spcifques
MoI-c|c 0rdrcjNcIIoyagc cmarquc
register DG/Appel Anciennement utilis par Borland
pour le fastcall
safecall ------/Appel Utilis en Delphi Borland pour
encapsuler les objets COM/OLE
syscall DG/Appelant Standard pour les API OS/2
optlink DG/Appelant Utilis par les compilateurs
VisualAge dIBM
Index
A
Abstraction 82
Accder
un lment, conteneur
standard 156
aux donnes dune table,
requte SQL 347
accumulate, algorithme
standard 214
adjacent_difference,
algorithme standard 215
adjacent_fnd, algorithme
standard 217
ADT (abstract data types) 82
advance, fonction 144
Agrgation 61
Ajouter, conteneur
standard 153
Algorithme standard
accumulate 214
adjacent_difference 215
adjacent_fnd 217
binary_search 218
copy 219
copy_backward 221
count 223
count_if 224
equal 225
equal_range 226
fll 228
fll_n 228
fnd 228
fnd_end 265
fnd_frst_of 229
fnd_if 228
for_each 230
foreach 304
generate 231
includes 232
inner_product 234
inplace_merge 243
iota 235
is_heap 236
is_sort 274
iter_swap 275
lexicographical_compare 238
lexicographical_compare_
3way 238
lower_bound 241
make_heap 236
max 245
max_element 246
merge 243
min 245
min_element 246
mismatch 247
next_permutation 248
428
I
N
0
L
X
uninitialized_fll 282
uninitialized_fll_n 282
unique 278
unique_copy 278
upper_bound 241
Alias 8
Voir aussi Raccourcis ; Liens
symboliques
Allocation dynamique 113
append, fonction 188
Assertion la compilation,
bibliothque BOOST 306
assign, fonction 179
at, fonction 156
auto, mot-cl, C++0x 399
8
back, fonction 156
back_insert_iterator 150
back_inserter 150
bad, fonction (fux) 195
Base de donnes
accder aux donnes dune
table, requte SQL 347
BEGIN TRANSACTION,
requte SQL 322
BETWEEN, requte SQL 348
COMMIT, requte SQL 322
CREATE TABLE,
requte SQL 338
crer la dfnition de table
et ouverture 352
crer une table,
requte SQL 338
dfnir un environnement 349
DISTINCT, requte SQL 347
fermer la connexion 357
A|gorIhmc sIandard, nIh_c|cmcnI
nth_element 250
partial_sort 251
partial_sort_copy 252
partial_sum 253
partition 254
pop_heap 236
power 256
prev_permutation 248
push_heap 236
random_sample 257
random_sample_n 258
random_shuffe 259
remove 260
remove_copy 262
remove_copy_if 262
remove_if 260
replace 263
replace_copy 263
replace_copy_if 263
reverse 264
reverse_copy 264
rotate 264
rotate_copy 264
search 265
search_n 265
set_difference 268
set_intersection 270
set_symetric_difference 272
set_union 273
sort 274
sort_heap 236
stable_partition 254
stable_sort 274
swap 275
swap_range 275
transform 276
uninitialized_copy 281
uninitialized_copy_n 281
421
I
N
0
L
X
BOOST_STATIC_ASSERT 306
expressions rgulires 291
caractres spciaux 294
object_pool 121
pointeurs faibles 298
pointeurs forts 296
pointeurs intelligents 295
pointeurs intrusifs 299
pointeurs locaux 299
pool 120
pool_alloc 122
singleton_pool 121
union de types scurise
300
binary_search, algorithme
standard 218
bool, mot-cl 29
boost
format, bibliothque
BOOST 286
get<>(variant), biblioth-
que BOOST 301
intrusive_ptr, classe, biblio-
thque BOOST 300
lexical_cast, bibliothque
BOOST 289
regex, classe, bibliothque
BOOST 292
regex_match, fonction,
bibliothque BOOST 292
regex_search, fonction,
bibliothque BOOST 293
scoped_array, classe, biblio-
thque BOOST 299
scoped_ptr, classe, biblio-
thque BOOST 299
\hared_array, classe, biblio-
thque BOOST 297
boost::sharcd_array, c|assc, hh|oIhcquc 800SJ
fermer la table 356
GROUP BY, requte SQL 347
jointure interne,
requte SQL 348
librer lenvironnement 358
ORDER BY,
requte SQL 324, 347
se connecter un base 350
SELECT, requte SQL 347
utiliser la table 355
WHERE, requte SQL 347
begin, fonction 154
BEGIN TRANSACTION, requte
SQL 322
BETWEEN, requte SQL 348
Bibliothque
dllexport 100
dllimport 100
Bibliothque BOOST
assertion la compilation 306
boost::format 286
boost::get<>(variant) 301
boost::intrusive_ptr, classe 300
boost::lexical_cast 289
boost::regex, classe 292
boost::regex_match,
fonction 292
boost::regex_search,
fonction 293
boost::scoped_array,
classe 299
boost::scoped_ptr, classe 299
boost::shared_array,
classe 297
boost::shared_ptr, classe 296
boost::variant 300
boost::weak_ptr, classe 298
BOOST_FOREACH 304
428
I
N
0
L
X
boost::sharcd_pIr, c|assc, hh|oIhcquc 800SJ
shared_ptr, classe, biblio-
thque BOOST 296
variant, bibliothque
BOOST 300
weak_ptr, classe, bibliothque
BOOST 298
BOOST_FOREACH,
bibliothque BOOST 304
BOOST_STATIC_ASSERT,
bibliothque BOOST 306
break, mot-cl 13
L
C++0x
auto, mot-cl 399
concept, mot-cl 402, 403, 405
constexpr, mot-cl 408
decltype, mot-cl 399
default, mot-cl 392
dlgation 388
delete, mot-cl 392
enum, mot-cl 395
explicit, mot-cl 395
expression constante 408
extern, mot-cl 407
fonction, syntaxe unife 401
for, mot-cl 400
initialisation avec une liste 396
initialisations 397
lambda fonctions 414
nullptr, mot-cl 411
requires, mot-cl 404
sizeof, mot-cl 406
template, mot-cl 410
template, syntaxe 407
template externe 407
thread_local, mot-cl 386
tuple 412, 413
Unicode 386
union, mot-cl 394
using, mot-cl 389
variadic template 410
case, mot-cl 10
catch, mot-cl 123, 125
cdecl, convention dappel 419
Chane de caractres
append, fonction 188
assign, fonction 179
chercher 182
compare, fonction 180
comparer 180
concatner 188
crer 178
changer 181
effacer une partie 189
empty, fonction 180
erase, fonction 189
extraire 184
fnd, fonction 183
fnd_frs_not_of, fonction 184
fnd_frst_of, fonction 184
getline, fonction 190
insrer 187
insert, fonction 187
istringstream (fux) 206
length, fonction 180
lire dans un fux 190
longueur 180
ostringstream (fux) 206
rechercher 182
remplacer une partie 185
replace, fonction 186
rfnd, fonction 183
size, fonction 180
string_stream 191
420
I
N
0
L
X
LLAJL JA8LL, rcquIc S0L
stringstream (fux) 205
substr, fonction 184
swap, fonction 181
Unicode 386
Chane de caractres (string,
wstring, crope, wrope),
conteneur standard 178
Choix du conteneur
standard 153
Classe
abstraite 82
de caractristiques 141
clear, fonction 154
COMMIT, requte SQL 322
compare, fonction 180
Composition 60
concept, mot-cl, C++0x 402,
403, 405
const, mot-cl 25, 58, 72
const_cast, mot-cl 34
constexpr, mot-cl, C++0x 408
Constructeur 68, 69
Conteneur standard
accder un lment 156
ajouter 153
chane de caractres (string,
wstring, crope, wrope) 178
choix 153
complexit algorithmique 173,
175
cration 152
ensemble (set) 166
FIFO 164
fle double entre
(deque) 161
insrer 153
LIFO 163
liste chane (list) 160
parcourir 154
pile (stack) 163
queue (queue) 164
queue de priorit
(priority_queue) 165
supprimer 154
table associative (map,
mutlimap) 167, 169
tableau (vector) 158
table de hashage (hash_map,
hash_set, hash_mutlimap,
hash_mutliset) 170
continue, mot-cl 13
Convention dappel
cdecl 419
fastcall 422
pascal 421
stdcall 422
thiscall 423
Conversion
de spcialisation 36
de type C 32
donne en chane de
caractres 289
explicite 70
qualit 39
transversale 36
copy, algorithme standard 219
copy_backward, algorithme
standard 221
copy_n,fonction 222
count, algorithme
standard 223
count, fonction 157
count_if, algorithme
standard 224
CREATE TABLE,
requte SQL 338
480
I
N
0
L
X
Lrccr unc Iah|c, rcquIc S0L
Crer une table,
requte SQL 338
crope (chane de caractres),
STL 178
0
decltype, mot-cl, C++0x 399
default, mot-cl, C++0x 392
Dlgation, C++0x 388
delete, mot-cl 113
C++0x 392
delete, oprateur,
redfnition 114
deque (fle double entre),
STL 161
Drfrencement 48
Destructeur 68, 69
distance, fonction 142
DISTINCT, requte SQL 347
dllexport, mot-cl 100
dllimport, mot-cl 100
DOM, XML 359
dowhile, mot-cl 12
dynamic_cast, mot-cl 36, 87
L
empty, fonction 180
Encapsulation 85
end, fonction 154
Ensemble (set, multiset),
conteneur standard 166
enum, mot-cl 7, 31
C++0x 395
eof, fonction (fux) 195
equal, algorithme standard 225
equal_range, algorithme
standard 226
erase, fonction 154, 189
Espace de noms 40
Exception 123, 125
expliciter 129
gestion des ressources 132
relancer 127
STL 134
terminate() 125, 131
transmettre 127
unexpected () 131
explicit, mot-cl 71
C++0x 395
Expression constante,
C++0x 408
Expressions rgulires
bibliothque BOOST 291
caractres spciaux 294
extern, mot-cl 44
C++0x 407
F
fail, fonction 195
fastcall, convention
dappel 422
Fichier
crire 200
tat 195
lire 197
mode 194
ouvrir 194
se dplacer dans 201
FIFO, conteneur standard 164
File double entre (deque),
conteneur standard 161
481
I
N
0
L
X
nc|udcs, a|gorIhmc sIandard
fll, algorithme standard 228
fll_n, algorithme standard 228
fnd, algorithme standard 228
fnd, fonction 157, 183
fnd_end, algorithme
standard 265
fnd_frs_not_of, fonction 184
fnd_frst_of, algorithme
standard 229
fnd_frst_of, fonction 184
fnd_if, algorithme
standard 228
fags, fonction (fux) 202
fush, fonction (fux) 200
Foncteurs 88
de la STL 92
Fonction
advance 144
copy_n 222
distance 142
embarque 46
membre 62
statique 73
syntaxe unife, C++0x 401
virtuelle pure 82
for, ensembliste, C++0x 400
for, mot-cl 12
for_each, algorithme
standard 230
foreach, algorithme
standard 304
format, bibliothque
BOOST 286
friend (mot-cl) 66
front, fonction 156
front_insert_iterator 149
front_inserter 149
0
gcount, fonction (fux) 198
generate, algorithme
standard 231
get, fonction (fux) 198
get<>(variant),
bibliothque BOOST 301
getline, fonction 190, 198
getline, fonction (fux) 199
good, fonction (fux) 195
goto, mot-cl 14, 43
GROUP BY, requte SQL 347
h
hash_map (table associative),
STL 170
hash_multiset (table de
hashage), STL 170
hash_set (table de
hashage), STL 170
Hritage
multiple 78
priv 77
protg 76
publique 76
simple 74
virtuel 79
visibilit 75
I
if, mot-cl 10
ignore, fonction (fux) 199
includes, algorithme
standard 232
482
I
N
0
L
X
Indirection 48
Information dynamique de
type 87
Initialisation
avec une liste, C++0x 396
C++0x 397
inline, mot-cl 46
inner_product, algorithme
standard 234
inplace_merge, algorithme
standard 243
Insrer, conteneur
standard 153
insert, fonction 187
insert_iterator 148
inserter 148
Instanciation explicite 99
intrusive_ptr, classe,
bibliothque BOOST 300
iota, algorithme standard 235
is_heap, algorithme
standard 236
is_sort, algorithme
standard 274
istream_iterator 145
istringstream (fux) 206
iter_swap, algorithme
standard 275
Itrateur 137
advance() 144
back_insert_iterator 150
back_inserter 150
classe de caractristique 140
concepts 138
dinsertion 148
en dbut 149
en fn 150
IndrccIon
distance 142
front_insert_iterator 149
front_inserter 149
insert_iterator 148
inserter 148
istream_iterator 145
ostream_iterator 146
reverse_bidirectional_itera-
tor 146
reverse_iterator 146
iterator_traits, STL 140
1
Jointure interne,
requte SQL 348
L
Lamba fonctions, C++0x 414
length, fonction 180
lexical_cast, bibliothque
BOOST 289
lexicographical_compare,
algorithme standard 238
lexicographical_compare_3way,
algorithme standard 238
Liens symboliques
Voir aussi Alias, Raccourcis
LIFO, conteneur standard 163
list (liste chane), STL 160
Liste chane (list),
conteneur standard 160
lower_bound, algorithme
standard 241
488
I
N
0
L
X
MoI-c|c, Ihrow
M
Macros 16, 17
make_heap, algorithme
standard 236
Manipulateur (fux) 203, 204
map (table associative),
STL 167, 169
max, algorithme standard 245
max_element, algorithme
standard 246
Membre
fonction 62
pointeur this 67
Mmoire
allocation dynamique 113
chec de rservation 116
handler 117
partage, QT 312
pool 120
merge, algorithme
standard 243
Mtaprogrammation 106
avantages et
inconvnients 111
mta-oprateurs 108, 109
min, algorithme standard 245
min_element, algorithme
standard 246
mismatch, algorithme
standard 247
Mot-cl
auto, C++0x 399
bool 29
break 13
case 10
catch 123, 125
concept, C++0x 402, 403, 405
const 25, 58, 72
const_cast 34
constexpr, C++0x 408
continue 13
decltype, C++0x 399
default, C++0x 392
delete 113
delete, C++0x 392
dowhile 12
dynamic_cast 36, 87
enum 7, 31
enum, C++0x 395
explicit 71
explicit, C++0x 395
extern 44
extern, C++0x 407
for 12
for, C++0x 400
goto 14, 43
if 10
mutable 58, 72
namespace 40
new 113
nothrow 119
nullptr, C++0x 411
reinterpret_cast 35
requires, C++0x 404
sizeof, C++0x 406
static 28, 42, 73
static_cast 33
struct 6, 31
switch 10
template 96
template, C++0x 410
thread_local, C++0x 386
throw 123, 125
484
I
N
0
L
X
MoI-c|c, Iry
try 123, 125
typedef 8
typeid 87
typename 99, 101
union 7, 31
union, C++0x 394
using 41
using, C++0x 389
virtual 79
void 42
volatile 318
wchar_t 31
while 12
multimap (table associative),
STL 167, 169
multiset (ensemble), STL 166
mutable, mot-cl 58, 72
Mutex, QT 313
N
name mangling 417
namespace, mot-cl 40
new, mot-cl 113
new, oprateur, redfnition 114
next_permutation, algorithme
standard 248
nothrow, mot-cl 119
nth_element, algorithme
standard 250
nullptr, mot-cl, C++0x 411
0
object_pool, BOOST 121
Oprateur
binaires 12
de comparaison 11
delete, redfnition 114
de placement 115
logiques 12
new, redfnition 114
priorit 18
ORDER BY, requte SQL 324, 347
ostream_iterator 146
ostringstream (fux) 206
P
Parcourir, conteneur
standard 154
partial_sort, algorithme
standard 251
partial_sort_copy, algorithme
standard 252
partial_sum, algorithme
standard 253
partition, algorithme
standard 254
pascal, convention dappel 421
Patron dalgorithme 88
peek, fonction (fux) 199
Pile (stack), conteneur
standard 163
Pointeurs 48
faibles, bibliothque BOOST 298
forts, bibliothque BOOST 296
intelligents, bibliothque
BOOST 295
intrusifs, bibliothque
BOOST 299
locaux, bibliothque
BOOST 299
Polymorphisme 82, 83
pool, BOOST 120
pool_alloc, BOOST 122
485
I
N
0
L
X
rnd, foncIon
Pool mmoire 120
pop_heap, algorithme standard
236
power, algorithme standard 256
Prprocesseur 16, 17
constantes 17
prev_permutation, algorithme
standard 248
printf, quivalent 286
private, hritage 75
private, mot-cl 75
protected, hritage 75
protected, mot-cl 75
public, hritage 75
public, mot-cl 75
push_back, fonction 154
push_front, fonction 154
push_heap, algorithme
standard 236
put, fonction (fux) 200
putback, fonction (fux) 200
0
Queue (queue), conteneur
standard 164
Queue de priorit
(priority_queue), conteneur
standard 165

Raccourcis Voir aussi Alias,


Liens symboliques
random_sample, algorithme
standard 257
random_sample_n, algorithme
standard 258
random_shuffe, algorithme
standard 259
rbegin, fonction 154
rdstate, fonction (fux) 196
read, fonction (fux) 199
Rfrences 29, 50
regex, classe, bibliothque
BOOST 292
regex_match, fonction,
bibliothque BOOST 292
regex_search, fonction,
bibliothque BOOST 293
reinterpret_cast, mot-cl 35
remove, algorithme
standard 260
remove_copy, algorithme
standard 262
remove_copy_if, algorithme
standard 262
remove_if, algorithme
standard 260
rend, fonction 154
replace, algorithme
standard 263
replace, fonction 186
replace_copy, algorithme
standard 263
replace_copy_if, algorithme
standard 263
requires, mot-cl, C++0x 404
reverse, algorithme
standard 264
reverse_bidirectional_itera-
tor 146
reverse_copy, algorithme
standard 264
reverse_iterator 146
rfnd, fonction 183
488
I
N
0
L
X
roIaIc, a|gorIhmc sIandard
rotate, algorithme standard 264
rotate_copy, algorithme
standard 264
RTTI (runtime type
information) 87
S
SAX
DOM 359
XML 359
scoped_array, classe,
bibliothque BOOST 299
search, algorithme
standard 265
search_n, algorithme
standard 265
seekg, fonction (fux) 201
seekp, fonction (fux) 201
SELECT, requte SQL 347
Smaphore, QT 316
set (ensemble), STL 166
set_difference, algorithme
standard 268
set_intersection, algorithme
standard 270
set_symmetric_difference,
algorithme standard 272
set_union, algorithme
standard 273
setf, fonction (fux) 202
shared_array, classe,
bibliothque BOOST 297
shared_ptr, classe,
bibliothque BOOST 296
singleton_pool, BOOST 121
size, fonction 180
sizeof, mot-cl, C++0x 406
sort, algorithme standard 274
sort_heap, algorithme
standard 236
Spcialisation
partielle 104
totale 102
SQLite 321
accder aux donnes dune
table, requte SQL 347
crer une base (API) 331
crer une base,
interprteur 328
crer une table,
requte SQL 338
installation 325
interprteur (sqlite3) 328
lancer une requte 335
lire des donnes 336
quand lutiliser 322
quand ne pas lutiliser 326
sqlite3_close, fonction 337
sqlite3_errmsg, fonction 332
sqlite3_errmsg16, fonction 332
sqlite3_fnalize, fonction 338
sqlite3_free, fonction 336
sqlite3_malloc, fonction 336
sqlite3_next_stmt, fonction 338
sqlite3_open*, fonction, codes
derreur 333, 334, 335
sqlite3_close, fonction 337
sqlite3_errmsg, fonction 332
sqlite3_errmsg16, fonction 332
sqlite3_fnalize, fonction 338
sqlite3_free, fonction 336
sqlite3_malloc, fonction 336
sqlite3_next_stmt, fonction 338
481
I
N
0
L
X
Icmp|aIc, moI-c|c
sqlite3_open*, fonction, codes
derreur 333, 334, 335
stable_partition, algorithme
standard 254
stable_sort, algorithme standard
274
stack (pile), STL 163
static, mot-cl 28, 42, 73
static_cast, mot-cl 33
stdcall, convention dappel 422
STL
crope (chane de
caractres) 178
deque (fle double
entre) 161
exceptions (liste) 134
foncteurs 92
hash_map (table de
hashage) 170
hash_multimap (table de has-
hage) 170
hash_multiset (table de
hashage) 170
hash_set (table de
hashage) 170
iterator_traits 140
list (liste chane) 160
map (table associative) 167, 169
muliset (ensemble) 166
multimap (table associative)
167, 169
priority_queue (queue de prio-
rit) 165
queue (queue) 164
set (ensemble) 166
stack (pile) 163
string (chane de caractres) 178
vector (tableau) 158
wrope (chane de
caractres) 178
wstring (chane de
caractres) 178
string (chane de caractres),
STL 178
stringstream (fux) 205
struct, mot-cl 6, 31
substr, fonction 184
swap, algorithme standard 275
swap, fonction 181
swap_range, algorithme
standard 275
switch, mot-cl 10
J
Table associative (map),
conteneur standard 167, 169
Tableau (vector), conteneur
standard 158
Table de hashage (hash_map,
hash_set, hash_mutlimap,
hash_mutliset), conteneur
standard 170
tellg, fonction (fux) 201
tellp, fonction (fux) 201
Template 96
bibliothque et 99
dfnition 95
externe, C++0x 407
mtaprogrammation 106
mot-cl, C++0x 410
spcialisation partielle 104
spcialisation totale 102
syntaxe, C++0x 407
template, mot-cl 96
488
I
N
0
L
X
IcrmnaIc(), cxccpIon
terminate(), exception 125, 131
this, pointeur 67
thiscall, convention dappel 423
Thread, QT 311
thread_local, mot-cl,
C++0x 386
throw, mot-cl 123, 125
traits
classe 141
dfnition 141
transform, algorithme
standard 276
try, mot-cl 123, 125
tuple, C++0x 412, 413
Type, information
dynamique 87
type_info, structure 87
typedef, mot-cl 8
typeid, mot-cl 87
typename, mot-cl 99, 101
u
UML, hritage multiple 78
unexpected(), exception 131
Unicode, C++0x 386
uninitialized_copy, algorithme
standard 281
uninitialized_copy_n,
algorithme standard 281
uninitialized_fll, algorithme
standard 282
uninitialized_fll_n,
algorithme standard 282
union, mot-cl 7, 31
C++0x 394
Union de types scurise,
bibliothque BOOST 300
unique, algorithme
standard 278
unique_copy, algorithme
standard 278
unsetf, fonction (fux) 202
upper_bound, algorithme
standard 241
using, mot-cl 41
C++0x 389
v
variadic template, C++0x 410
variant, bibliothque
BOOST 300
vector (tableau), STL 158
virtual, mot-cl, hritage 79
Virtuel, hritage 79
void, mot-cl 42
volatile, mot-cl 318
W
wchar_t, mot-cl 31
weak_ptr, classe, bibliothque
BOOST 298
WHERE, requte SQL 347
while, mot-cl 12
write, fonction (fux) 200
wrope (chane de caractres),
STL 178
wstring (chane de
caractres), STL 178
wxDb, classe 350
wxDbCloseConnections,
fonction 357
wxDbConnectInf, classe 349
480
I
N
0
L
X
XML, manpu|cr dcs donnccs
wxDbFreeConnection,
fonction 357
wxDbGetConnectInf, classe 350
wxDbTable Query, fonction 355
wxXmlDocument, classe 360
wxXmlNode, classe 364
wxXmlProperty, classe 363
X
XML
charger un fchier 360
DOM 359
manipuler des donnes 363
Proprit de Client ePagine <3437341@epagine.fr>
customer 26505 at Tue Feb 15 02:49:55 +0100 2011
Vincent Gouvernelle
C
+
+
L
E

G
U
I
D
E

D
E

S
U
R
V
I
E
V. Gouvernelle
LE GUI DE DE SURVI E
C
++
L ESSENTI EL DU CODE ET DES COMMANDES
Ce Guide de sur vie est le compagnon indispensable
pour programmer en C++ et ut iliser ef cacement les
bibliot hques st andard STL et BOOST, ainsi que QT,
wxWidget et SQLit e. Cet ouvrage prend en compt e la
fut ure norme C++0x.
CONCIS ET MANIABLE
Facile t ranspor t er, facile ut iliser nis les livres
encombrant s !
PRATIQUE ET FONCTIONNEL
Plus de 150 squences de code pour programmer
rapidement et ef cacement en C++.
Vincent Gouvernelle est ingnieur en informat ique, diplm
de l ESIL Marseille, et t it ulaire d un DEA en informat ique.
Il t ravaille act uellement chez Sescoi R&D, socit dit rice de
logiciels spcialiss dans la CFAO (concept ion et fabricat ion
assist e par ordinat eur).
Niveau : Int ermdiaire / Avanc
Cat gorie : Programmat ion
Con gurat ion : Mult iplat e-forme
LE GUI DE DE SURVI E
C
++
L ESSENTI EL DU CODE ET DES COMMANDES
Pearson Education France
47 bis, rue des Vinaigriers
75010 Paris
Tl. : 01 72 74 90 00
Fax : 01 42 05 22 17
www.pearson.fr
ISBN : 978-2-7440-4011-5
2281-GS C++.indd 1 11/05/09 15:56:39

Vous aimerez peut-être aussi