You are on page 1of 115

Allocation dynamique de tableaux et de structures

Mmoire
La mmoire d'un ordinateur est compose d'un grand nombre d'octets (une valeur
entre 0 et 255) :
adresse

octet

0
1
2
3

Chaque octet est repr par une adresse, qui est un nombre entier.

Les variables sont stockes en mmoire. Par exemple:


int a(3);
adresse

contenu

24996
25000
25004

25008

25012

25016

25020

L'oprateur &
On peut obtenir l'adresse d'une variable grce l'oprateur &:
Par exemple:
int a(3);
cout << a << endl;
cout << (unsigned int)(&a) << endl;
va afficher pour cet exemple:
3
25004

adresse

contenu

24996
25000
25004

25008

25012

25016

25020

Stocker une adresse dans une variable


En C et en C++, on peut dfinir des variables pour qu'elles contiennent
des adresses.
Pour dclarer une telle variable, Il faut ajouter une toile * entre le type
et le nom de la variable:
int * p;
p est appel un pointeur.

Stocker une adresse dans une variable


Si on fait:

adresse

contenu

24996

int * p;
p = &a;

25000
25004
25008

p contient l'adresse de a.

25012
25016
25108

3
?

25004
?
p

Reprsentation graphique (1)


p contient l'adresse de a.
On dit que p pointe sur a.
La valeur de l'adresse de a n'est pas
importante en elle-mme, ce qui est
important est que p pointe sur a.
Ceci est souvent reprsent par une flche
allant de p a.

adresse

contenu

24996
25000
25004

3
?

25008
25012
25016
25108

Reprsentation graphique (2)

On n'a gnralement pas besoin de la reprsentation de la mmoire, et


on peut ne garder que la reprsentation des variables.
int a(3);
int * p;
p = &a;

3
a
p

L'oprateur *
L'oprateur * permet d'accder la valeur stocke une adresse:
cout << *p << endl;
affiche 3.

3
a
p

Modifier la valeur pointe par un pointeur


On peut aussi utiliser l'oprateur pour modifier une valeur pointe par
un pointeur:
int a(3);
int * p;

p = &a;

a
*p = 5;

Attention ne pas confondre


l'toile utilise pour dclarer un pointeur:
int * p;

Mme symbole (*) mais


signification diffrente.

et l'toile pour obtenir la valeur pointe par le pointeur:


*p = 5;

Rsum
Un pointeur est une variable. On dclare un pointeur en mettant une
toile (*) entre le type et le nom du pointeur:
int * p;
Un pointeur contient une adresse.
On peut obtenir l'adresse d'une variable avec l'oprateur &:
int a = 0;
p = &a;
L'oprateur * permet d'accder la mmoire pointe par un pointeur:
int b = *p;
*p = 1;

0
b

Dclaration d'un pointeur


Un pointeur est une variable:
On peut dclarer plusieurs pointeurs sur une mme ligne, et initialiser
un pointeur lors de sa dclaration. Exemples:
double a;
double * p1(&a);
int * p2, * p3;
Attention: pour dclarer plusieurs pointeurs sur une mme ligne, il
faut rpter l'toile. Si on fait:
int * p2, p3; // !!
p2 est de type pointeur sur int, mais p3 est une variable classique,
de type int .

Le pointeur NULL ou 0
On utilise parfois la valeur 0, ou la constante NULL (de type pointeur, qui vaut
0) pour initialiser un pointeur:
int * p = 0;
ou
int * p = NULL;
L'adresse 0 n'est jamais utilise pour stocker des variables, elle correspond
donc toujours une adresse invalide: Si on essaie d'accder la valeur
pointe par p en faisant par exemple:
int * p = 0;
int a = *p;
*p = 12;
on provoque un:
Segmentation fault
L'intrt du pointeur NULL est par exemple de signaler qu'une fonction n'a
pas pu fonctionner correctement, ou qu'un pointeur ne contient pas une
adresse valide.

Remarques
On peut voir l'oprateur * comme l'inverse de l'oprateur &:
b = *(&a);
est quivalent
b = a;

On peut mettre zro, un ou plusieurs espaces avant et aprs l'toile et


le et commercial:
int *pa = & a;
b = * pa;

Affectation de pointeurs
On peut affecter un pointeur la valeur d'un autre pointeur de mme
type.

Exemple:
int n(1), p(2);
int * ad1, * ad2;
Que font les instructions:
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

Pas--pas
1

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

Pas--pas
1

ad1 pointe sur n

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

Pas--pas
1

ad2 pointe sur p

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

Pas--pas
15

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

exactement comme n = p + 3;
n contient maintenant 5

Pas--pas
5

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

Pas--pas
5

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

ad1 et ad2 pointent maintenant tous les


deux sur p.

Pas--pas
5

int n(1), p(2);


int * ad1, * ad2;
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;

ad1

ad2

exactement comme p = p + 5;
p contient donc maintenant 7

Exercice
int a(2), b(5);
int * p;
p = &a;
cout << a << " " << *p << endl;
a = a + 1;
cout << a << " " << *p << endl;
*p = b;
cout << a << " " << *p << endl;
b = b + 1;
cout << a << " " << *p << endl;

Pointeur en paramtre d'une fonction

Rappel
Si on excute:
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
mis_a_zero(n);
}

cout << "apres appel: n = " << n << endl;

on obtient:
apres appel: n = 10
La fonction mis_a_zero ne peut pas changer la valeur de n !

Pas--pas
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}

10
n

Pas--pas
10
a
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}

10
n

Pas--pas
10
a
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}

10
n

Pas--pas
0
a
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}

10
n

Pas--pas

void mis_a_zero(int a)
{
a = 0;
}

10

int main()
{
int n = 10;

cout << "avant appel: n = " << n << endl;


mis_a_zero(n);
cout << "apres
}

Mme si la fonction a chang les valeurs du


appel:
n = " << formels
n << endl;
paramtres
a, le changement n'est pas
rpercut sur le paramtre effectif n.

Une fonction modifiant


une variable passe en paramtre
Pour que la fonction puisse modifier la variable n, il y a deux options en
C++:
soit utiliser un passage par rfrence,
soit utiliser un pointeur.
Nous avons dj vu le passage par rfrence. Nous allons voir la
solution avec un pointeur.

Une fonction modifiant


une variable passe en paramtre
Pour que la fonction puisse modifier la variable n, il faut passer en
paramtre l'adresse de la variable plutt que sa valeur:
void mis_a_zero(int * pa)
{
*pa = 0;
}
int main()
{
int n = 10;
mis_a_zero(&n);
}

cout << "apres appel: n = " << n << endl;

on obtient cette fois:


apres appel: n = 0

Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}

10

int main()
{
int n = 10;
mis_a_zero(&n);
}

n
1. La variable n est cre en mmoire

cout << "apres appel: n = " << n << endl;

Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}

10

int main()
{
int n = 10;
mis_a_zero(&n);
}

n
2. L'adresse de la variable n est passe en paramtre.

cout << "apres appel: n = " << n << endl;

Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}

3. Le paramtre pa est cr,


l'adresse de n est copie dans pa.

pa

int main()
{
int n = 10;
mis_a_zero(&n);
}

cout << "apres appel: n = " << n << endl;

10
n

Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}

pa

4. On met 0 dans la mmoire


pointe par pa.
Comme pa pointe sur n, on met 0
dans n.

int main()
{
int n = 10;
mis_a_zero(&n);
}

cout << "apres appel: n = " << n << endl;

10 0

Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}

int main()
{
int n = 10;

mis_a_zero(&n);
}

cout << "apres appel: n = " << n << endl;


5. Aprs l'appel la fonction, n a
bien t modifie.

void mis_a_zero(int * pa)


{
*pa = 0;
}

On peut vrifier que le type du paramtre


effectif (&n) est bien le mme que celui
du paramtre formel (int * pa).

int main()
{
int n = 10;
mis_a_zero(&n);
}

cout << "apres appel: n = " << n << endl;

Exercice
void f(int * p, int q)
{
*p = *p + q;
}
void g(int * r)
{
f(r, 1);
}
int a = 0, b = 2;
f(&a, b);
cout << a << " " << b << endl;
g(&a);
cout << a << " " << b << endl;

Une fonction peut modifier


les lments d'un tableau
pass en paramtre

Tableaux et pointeurs
Utilis seul, le nom du tableau correspond l'adresse du premier
lment.
Par exemple, on peut faire:
int T[5];
int * tab = T;

tab

et tab pointe alors sur le premier lment de T.


Attention, T n'est pas pour autant un pointeur.
On ne peut pas faire par exemple:
T = &a;
si T a t dclar comme un tableau.

adresse

contenu

19996
T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

Tableaux et pointeurs

Aprs:

tab

int T[5];
int * tab = T;
tab pointe sur le premier lment de T.
*tab correspond donc T[0], le premier lment de T.
tab + 1 est l'adresse du deuxime lment de T.
*(tab + 1) correspond donc T[1], le deuxime
lment de T.
etc...

adresse

contenu

19996
T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

Notez que:
Si
tab vaut 20000,
et si tab est un pointeur sur int
Alors
tab + 1 vaut 20004
pour pointer sur le int suivant: un int est reprsent sur 4 octets, et les adresses
sont dfinies en octet.

Ce mcanisme de calcul simplifie l'accs aux lments du tableau: il n'y a pas savoir
qu'il faut multiplier par 4 dans le cas des int, par 8 dans le cas des double, etc...

Tableaux et pointeurs

Aprs:
int T[5];
int * tab = T;
tab pointe sur le premier lment de T.
*tab correspond donc T[0], le premier lment de T.

tab
adresse

contenu

19996
T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

tab + 1 est l'adresse du deuxime lment de T.


*(tab + 1) correspond donc T[1], le deuxime lment de T.20016
20020
On peut galement crire tab[1] la place de *(tab + 1).

T[4]

En C et en C++, on peut crire


tab[i]
la place de
*(tab + i)
ce qui permet d'utiliser tab comme on utiliserait un
tableau!

Qu'affiche le code suivant ?


int T[10];
for(int i = 0; i < 10; i++)
T[i] = i * i;
int * p = T, * q = &(T[2]);
cout << "A) " << *p << ", " << p[0] << ", " << p[1] << endl;
p++;
cout << "B) " << *p << ", " << p[0] << ", " << p[1] << endl;
cout << "C) " << *q << ", " << q[0] << ", " << q[1] << endl;
p = q + (q p);
cout << "D) " << *p << ", " << p[0] << ", " << p[1] << endl;

Accs aux lments d'un tableau


Supposons qu'on veut crire une fonction qui ajoute 1 aux lments d'un
tableau. On peut donc crire cette fonction comme a:
void ajoute1_aux_elements(int * tab)
{
for(int i(0); i < 5; ++i) {
*(tab + i) = *(tab + i) + 1;
}
}
ou comme a:
void ajoute1_aux_elements(int * tab)
{
for(int i(0); i < 5; ++i) {
tab[i] = tab[i] + 1;
}
}
et on peut appeler cette fonction ainsi:
int T[5];
ajoute1_aux_elements(T);

tab
adresse

contenu

19996
T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

void ajoute1_aux_elements(int * tab)


{
for(int i(0); i < 5; ++i) {
tab[i] = tab[i] + 1;
}
}
...

adresse

contenu

19996
int T[5];
ajoute1_aux_elements(T);

T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

void ajoute1_aux_elements(int * tab)


{
for(int i(0); i < 5; ++i) {
tab[i] = tab[i] + 1;
}
}
...

tab
adresse

contenu

19996
int T[5];
ajoute1_aux_elements(T);

T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

0
i

void ajoute1_aux_elements(int * tab)


{
for(int i(0); i < 5; ++i) {
tab[i] = tab[i] + 1;
}
}
...

tab
adresse

contenu

19996
int T[5];
ajoute1_aux_elements(T);

T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

void ajoute1_aux_elements(int * tab)


{
for(int i(0); i < 5; ++i) {
tab[i] = tab[i] + 1;
}
}
...

tab
adresse

contenu

19996
int T[5];
ajoute1_aux_elements(T);

T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

void ajoute1_aux_elements(int * tab)


{
for(int i(0); i < 5; ++i) {
tab[i] = tab[i] + 1;
}
}
...

tab
adresse

contenu

19996
int T[5];
ajoute1_aux_elements(T);

T = 20000

T[0]

20004

T[1]

20008

T[2]

20012

T[3]

20016

T[4]

20020

On peut crire indiffremment:


void ajoute1_aux_elements(int tab[5])
ou
void ajoute1_aux_elements(int * tab)
Le 5 du premier en-tte N'est PAS considr par le compilateur.
On peut mme crire:
void ajoute1_aux_elements(int tab[])

On peut crire indiffremment:


void ajoute1_aux_elements(int tab[5])
ou
void ajoute1_aux_elements(int * tab) Utilisez cette notation
Le 5 du premier en-tte N'est PAS considr par le compilateur.
On peut mme crire:
void ajoute1_aux_elements(int tab[])

Attention au nombre d'lments


La fonction
void ajoute1_aux_elements(int * tab)
ne connat PAS LA TAILLE du tableau pass en paramtre.

Passer le nombre d'lments en paramtre


Pour que la fonction puisse tre utilise pour n'importe quel tableau, quelle
que soit sa taille, on peut passer la taille du tableau en paramtre.
Exemple:
void ajoute1_aux_elements(int * tab, int nb_elements)
{
for(int i(0); i < nb_elements; ++i) {
tab[i] = tab[i] + 1;
}
}
Exemple d'utilisation:
int T[5], U[101];
...
ajoute1_aux_elements(T, 5);
ajoute1_aux_elements(U, 101);

void f(int * q, int r)


{
q = q + r;
*q = 0;
}
void g(int * q, int r)
{
q[r] = 0;
}
...
int T[4] = {1, 5, 6, 9};
int * p = T;
*p = *p + 1;
cout << T[0] << " " << T[1] << endl;
p = p + 1;
cout << T[0] << " " << T[1] << endl;
*p = *p + 1;
cout << T[0] << " " << T[1] << endl;
f(T, 2);
cout << T[2] << " " << T[3] << endl;
g(T, 3);
cout << T[2] << " " << T[3] << endl;

Exercice

Allocation dynamique:
Allouer de la mmoire
pendant l'excution du programme

Allouer de la mmoire
pendant l'excution du programme
On peut allouer de la mmoire pendant l'excution du programme.
On parle d'Allocation dynamique.
L'allocation se fait avec l'instruction new.
Une fois que la mmoire alloue n'est plus utile, IL FAUT la librer,
avec l'instruction delete.

Allouer de la mmoire
pendant l'excution du programme
int * tab;
tab = new int[5];

tab

L'instruction new fait 2 choses:


1. Elle alloue de la mmoire, c'est--dire qu'elle
rserve une partie de la mmoire de l'ordinateur
pour que le programme puisse l'utiliser.

mmoire

Allouer de la mmoire
pendant l'excution du programme
int * tab;
tab = new int[5];

tab

L'instruction new fait 2 choses:


1. Elle alloue de la mmoire, c'est--dire qu'elle
rserve une partie de la mmoire de l'ordinateur
pour que le programme puisse l'utiliser.
2. Elle renvoie l'adresse du dbut de cette
mmoire.
Dans notre exemple, tab va donc pointer sur
cette mmoire, et permettre au programme de
l'utiliser.

mmoire

Allouer de la mmoire
pendant l'excution du programme
int * tab;
tab = new int[5];

tab

tab[2] = 10;
tab[3] = 5 * tab[2];
delete [] tab;
L'instruction delete libre la mmoire alloue
par new, c'est--dire que cette partie de la
mmoire va pouvoir tre utilise par d'autres
programmes.
Le programme n'a plus le droit d'accder
cette partie de la mmoire.

mmoire

new et delete
Allocation de la mmoire:

tab = new int [5];

Libration de la mmoire:

delete []

tab;

new et delete
Nombre d'lments allouer

Allocation de la mmoire:

tab = new int [5];


Retourne l'adresse du
premier lment allou:
T doit tre dclar
comme un pointeur sur
int.

Type des lments

Libration de la mmoire:

Adresse de dbut de
la mmoire librer

delete []
Attention ne pas
oublier les crochets [ ]

tab;

void set(int * tab, int nb_elements, int v)


{
for(int i(0); i < nb_elements; ++i) {
tab[i] = v;
}
}
int main()
{
int * T;
int n;
cout << "Combien voulez-vous d'elements ?" << endl;
cin >> n;
T = new int[n];
// On met tous les elements de T a 0
set(T, n, 0);
//..
// il ne faut pas oublier de liberer la memoire allouee pour T
delete [] T;
return 0;
}

Fonction qui alloue un tableau

int * cree_tableau(int nb_elements)


{
int * T;
T = new int[nb_elements];
return T;
}
Le rsultat de la fonction est un pointeur sur le premier
lment du tableau.
Exemple d'utilisation:
int * T = cree_tableau(10);

Fonction qui alloue un tableau


le rsultat de la fonction est
de type pointeur sur int
int * cree_tableau(int nb_elements)
{
int * T;
T = new int[nb_elements];
la fonction renvoie l'adresse
return T;
premier lment du tableau
}
Le rsultat de la fonction est un pointeur sur le premier
lment du tableau.
Exemple d'utilisation:
int * T = cree_tableau(10);

du

On peut aussi crire cree_tableau de faon plus directe:


int * cree_tableau(int nb_elements)
{
return new int[nb_elements];
}

Le type de la fonction est cohrent


avec le type de son rsultat
int * cree_tableau(int nb_elements)
{
int * T;
T = new int[nb_elements];
return T;
}
int * cree_tableau(int nb_elements)
{
return new int[nb_elements];
}

T est un pointeur sur int

L'expression
new int[nb_elements] est
un pointeur sur int

Autre fonction qui alloue un tableau


Fonction qui alloue et remplit un tableau avec des valeurs alatoires:
int * cree_tableau_aleatoire(int nb_elements, int val_max)
{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

Exemple d'utilisation:
int * T = cree_tableau_aleatoire(5, 100);

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

int * T = cree_tableau_aleatoire(5, 100);

100

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

int * T = cree_tableau_aleatoire(5, 100);

100

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

mmoire

?
?

int * T = cree_tableau_aleatoire(5, 100);

?
?
?

100

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

resultat
mmoire

?
?

int * T = cree_tableau_aleatoire(5, 100);

?
?
?

100

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

resultat
mmoire

56
34

int * T = cree_tableau_aleatoire(5, 100);

82
17
39

100

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

resultat
mmoire

56
34

int * T = cree_tableau_aleatoire(5, 100);

82
17
39

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

mmoire

56
34

int * T = cree_tableau_aleatoire(5, 100);

82
17
39

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

mmoire

56
34

int * T = cree_tableau_aleatoire(5, 100);

82
17
39

resultat

int * cree_tableau_aleatoire(int nb_elements, int val_max)


{
int * resultat = new int[nb_elements];
for(int i(0); i < nb_elements; ++i) {
resultat[i] = rand() % val_max;
}
}

return resultat;

mmoire

56
34

int * T = cree_tableau_aleatoire(5, 100);

82
17
39

resultat

Allocation dynamique de
structures

Allocation d'une structure


struct Chat
{
string nom;
double poids;
};

alloue de la mmoire pour une


seule structure Chat

...

Chat * c = new Chat;

c: pointeur sur Chat

delete c;

libre la mmoire pointe par c

Allocation d'une structure


struct Chat
{
string nom;
double poids;
};
...
Chat * c = new Chat;

nom
0.0
poids

Allocation d'une structure


struct Chat
{
string nom;
double poids;
};
...
Chat * c = new Chat;

nom
0.0
poids

Accder aux champs


struct Chat
{
string nom;
double poids;
};
...
Chat * c = new Chat;

(*c).poids = 2.5;

nom
2.5
poids

L'oprateur ->
La notation
(*c).poids
n'est pas trs lisible.
Il existe un oprateur, not -> (un signe moins -, un signe suprieur
>), qui permet d'crire des expressions quivalentes mais plus lisibles:
c->poids

c->poids est quivalent (*c).poids

. ou -> ?
A gauche de . on trouve forcment une variable de type structure:
Chat c;
c.poids = 2.5;

A gauche de -> on trouve forcment un pointeur sur structure:


Chat * pc = &c;
pc->poids = 2.5;

Messages d'erreur
A la compilation de:
Chat c;
c->poids = 2.5; // !!
on obtient l'erreur:
error: base operand of `->' has non-pointer type `Chat'
c n'est pas un pointeur et appliquer l'oprateur -> sur c n'a donc pas de sens.
A la compilation de:
Chat * pc;
pc.poids = 2.5; // !!
on obtient l'erreur:
error: request for member `poids' in `pc', which is of non-class
type `Chat*'
L'oprateur . s'applique sur une structure, pas un pointeur comme pc est ici.

Fonction qui alloue une structure


le rsultat de la fonction est
de type pointeur sur Chat
Chat * cree_chat(string nom, double poids)
{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;
return c;
}

la fonction renvoie l'adresse de


la structure alloue

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;
return c;
}
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

"Felix"

2.5

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;
return c;
}
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

"Felix"

2.5

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;
return c;
}
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

c
2.5

"Felix"

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;

nom
0.0

return c;
}

poids

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

c
2.5

"Felix"

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;

nom

f
0.0

return c;
}

poids

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

c
2.5

"Felix"

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;

nom

f
2.5

return c;
}

poids

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

c
2.5

"Felix"

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;

nom

f
2.5

return c;
}

poids

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;

nom

f
2.5

return c;
}

poids

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

Chat * cree_chat(string nom, double poids)


{
Chat * c = new Chat;
c->nom = nom;
c->poids = poids;

nom

f
2.5

return c;
}

poids

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);

Pointeur sur structure en paramtre


d'une fonction

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

2.5
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

2.5
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom
?
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

?
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

?
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

?
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

?
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

?
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

3.2
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

3.2
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

void demande_poids(Chat * chat)


{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}

nom

3.2
poids

g2

Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);

You might also like