Examen 1 - pointeurs et allocation dynamique Flashcards

1
Q

Données (Data segment

A

pour les variables globales et statiques

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Code (code segment)

A

pour le code compilé

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Tas (Heap)

A

pour l’allocation dynamique

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Pile (Stack)

A

pour les variables locales

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

void UneFonction (int nombre3);
int nombre1;
void main()
{
Ennemi * e1;
e1 = new Ennemi;
UneFonction(7);
}
void UneFonction(int nombre3)
{
int nombre2;
}
cptInstance
nombre1
nombre2
nombre3
e1 (pointeur)
Pile
Tas
Code
Données
Main()
e1
(contenu)
class Ennemi
{
static int cptInstance;
// . . .
};

A

cptinstance et nombre 1 données
rien code
e1 (contenu) tas
nombre2 nombre3 e1(pointeur) pile

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

(la taille d’un int)

A

4 octets

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

transtyper l’adresse de a (un int*) en…. pour pouvoir visualiser le contenu de la mémoire un octet à la fois

A

pointeur de caractères
(unsigned char*)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Passage par valeur

A

Supposons que l’on possède la déclaration de fonction suivante :
int doIt(int value){
{
return value+1;
}
Supposons que l’on fasse l’appel
int b = doIt(a);
En supposant que la variable value soit à l’emplacement mémoire 0x009efda8 on obtiendra lors
de l’appel de doIt le schéma mémoire suivant :
a
52 0 0 0
0x00effc08 0x00effc09 0x00effc0A 0x00effc0B
value
52 0 0 0
0x009efda8 0x009efda9 0x009efdaA 0x009efdaB
Nous obtiendrons deux emplacements mémoire distincts qui contiendront cependant les mêmes
valeurs

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Passage par référence

A

Lorsque l’on passe un paramètre par référence, on utilise l’adresse de l’original. Une fa çon
d’obtenir l’adresse de l’original est d’utiliser l’opérateur &.
int a = 52;
int* ptrA = &a;
Si l’on veut accéder ce qui se trouve à une adresse on utilise l’opérateur *.
int valeurDeA = *ptrA;
// Évidemment ici valeurDeA et a auront la même valeur soit 52

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

ne fa çon
d’obtenir l’adresse de l’original

A

l’opérateur &

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Si l’on veut accéder ce qui se trouve à une adresse

A

l’opérateur *

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Si l’on exécute les instructions suivantes :
int a = 52;
int* ptrA = &52;
int* pValeur = ptrA + 1;

A

la valeur de pValeur sera celle de ptrA augmentée de 4 octets car ptrA est un pointeur de int
et un int occupe 4 octets en mémoire.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

int* pData;

A

// Ne pointe vers RIEN DE CONCRET. On ne veut pas faire cela.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

intialiser un pointeur

A

int* pData = new int;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

est alors possible d’accéder au contenu de pData pour y placer des infos ou pour lire le contenu

A

std::cout &laquo_space;*pData;
ou
*pData = 80;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Si vous tentez de lire le contenu d ’un emplacement mémoire AVANT d’y affecter une valeur,…

A

le
contenu est indéterminé

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

responsables de libérer la mémoire allouée avec new
lorsqu’elle n’est plus nécessaire.

A

delete pData; Le pointeur peut alors être réutilisé pour un autre emplacement mémoire mais le contenu
désormais pointé est indéterminé.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

void doIt()
{
int * pData = new int;
pData = 80;
}
void main()
{
doIt();
}

A

A la fin de l’exécution de la fonction doIt, la portée de la variable local pData sera terminée. La
variable sera libérée MAIS PAS L’ESPACE MÉMOIRE POINTÉ par pData. Cela causera une fuite de
mémoire

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

chaque utilisation de new doit s’accompagner

A

d’un delete
correspondant.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

une fonction ou une méthode qui alloue la mémoire
est

A

généralement responsable de la libérer. En programmation objet, l’objet qui allouera de la
mémoire sera responsable de la libérer lorsque sa portée prendra fin.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Allocation d’un tableau

A

int* pData = new int[10];

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Pour accéder à un élément d’un tableau

A

std::cout &laquo_space;pData[4];
est l’équivalent de
std ::cout &laquo_space;*(pData+4);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Pour libérer un tableau

A

int* pData = new int[10];
// …
delete[] pData;

24
Q

Vous comprenez maintenant pourquoi les tableaux sont indexés à partir de 0 et non de 1

A

C’est
parce que l’indice correspond au décalage par rapport à l’adresse du tableau.

25
Q

int a = 5; //&a est

A

la référence (l’adresse) du premier
octet de la structure (ici, un entier)

26
Q

int * p; //variable de type

A

adresse pouvant recueillir la
référence (adresse) d’un entier stocké en mémoire p = &a;

27
Q

int * p = new int;

A

« allocation d’un bloc mémoire pouvant contenir un entier, la
variable p reçoit l’adresse du premier octet de ce bloc »
À ce stade-ci le bloc est créé en mémoire mais il contient une
donnée invalide (« junk »)

28
Q

int * p = new int;
*p = 52;
On utilise l’opérateur « * »

A

pour affecter une valeur du type qui a été
déclaré

29
Q

Statique

A

signifie que la mémoire pour ce tableau est allouée au moment de la compilation, pas dynamiquement pendant l’exécution.

30
Q

Type des éléments (int *) pour un tab

A

Chaque élément du tableau est un pointeur vers un entier.
Cela signifie que chaque élément peut stocker l’adresse mémoire d’un entier.

31
Q

initialiser un tab de pointeur

A

int* tab[10];

for (int i = 0; i < 10; i++) {
tab[i] = new int(0); // Alloue dynamiquement un int initialisé à 0
}

32
Q

int * tab[10];
int a = 12;
tab[0] = &a;
Rien de dynamique dans cette approche, rien à faire non plus
lorsqu’on n’a plus besoin de ce tableau (tout est sur la stack).

A

Ne surtout pas faire de delete sur tab[0], il ne réfère pas à une
allocation dynamique (l’exécution va planter)

33
Q

int * tab[10];
tab[0] = new int;
*tab[0] = 12 //même principe avec l’étoile

A

Cette fois-ci il y a un new: toutes les adresses stockées dans le
tableau vont pointer vers un bloc dynamique, il faut en faire la
suppression ! delete[] tab;
Ne fonctionne pas ici, cette instruction fonctionnait lorsqu’on avait
l’adresse du premier octet vers un tableau dynamique

34
Q

supression tab de pointeur

A

for(int j = 0; j < 10; j++)
{
delete tab[ j ]; //suppression de tous les blocs dynamiques
}

35
Q

Dans le cas d’une instance de classe, on veut accéder à des
méthodes ou propriétés de la classe
Sur une instance déclarée sur la stack,

A

nous connaissons déjà la
syntaxe avec l’opérateur d’accès « . » :
Ennemi e;
e.attaquer();

36
Q

En allocation dynamique pour acceder methode

A

on utilise simplement l’opérateur
d’accès « -> »
Ennemi * ptrEnnemi = new Ennemi();
ptrEnnemi->attaquer();
La dernière instruction est l’équivalent de
*(ptrEnnemi).attaquer();
Si pour une raison quelconque ptrEnnemi est null ou invalide,
l’exécution va s’arrêter avec une erreur de mémoire

37
Q

Destructeur

A

Le destructeur d’une classe (méthode spéciale préfixée du symbole
« ~ » est la dernière méthode appelée avant la suppression définitive
de l’instance en mémoire :

38
Q

void attaquerEnnemi()
{
Ennemi e;
e.attaquer();
int a = 38;
[…]
} ou est appeler destructeur (exemple stack)

A

à la sortie de cette méthode, la stack est libérée de la variable
locale « e », le destructeur de la classe Ennemi sera appelé.

39
Q

xemple (sur la heap) :
void attaquerEnnemi()
{
Ennemi * ptrEnnemi = new Ennemi();
ptrEnnemiattaquer();
delete ptrEnnemi; //Le destructeur de la classe
Ennemi est appelé ici;
int a = 38
[…]
}

A

you knooow

40
Q

Ennemi * tabEnnemis = new Ennemi[10]; comment utiliser methode ?

A

tabEnnemis[0].attaquer();
Il faut garder en tête que ce ne sont pas des pointeurs

41
Q

Ennemi * tabEnnemis[10]; comment utiliser methode ?

A

Cette fois-ci, on va stocker des adresses vers des instances de la
classe Ennemi
tabEnnemis[0]attaquer();
Cette fois-ci ce sont des pointeurs

42
Q

Une classe garde la référence d’une autre classe dans une
de ses variables Composition de classes

A

Habituellement on ne touche pas à cette référence, on
laisse la stack faire son travail ! Composition faible

43
Q

Composition de classes Une classe alloue dynamiquement une autre classe et
stocke l’adresse reçue dans une variable

A

Habituellement, la classe qui alloue la mémoire
s’occupe de la libérer Composition forte

44
Q

Le mode par référence permet de

A

passer la valeur originale d’une variable en paramètre à une méthode.
En plus d’éviter de prendre une copie indépendante souvent inutile, le passage par référence permet
3
aussi à cette méthode de modifier le paramètre reçu et donc la valeur initiale. C’est un peu l’équivalent du
mot clé ref en C#.

45
Q

utilité contructeur copie

A

Le problème est que les ennemies dans la classe héro ne sont pas copié en profondeur. La première cela
marche, mais ensuite lorsqu’il faut y ré-accéder le problème est que par défaut seul le premier ennemy est
copier car c’est là que pointe le pointeur.

46
Q

N’oubliez pas d’utiliser le modificateur override même s’il n’est pas strictement obligatoire. Au
fait, pourquoi doit-on le mettre s’il n’est pas obligatoire?

A

On doit le mettre pour signaler au compilateur que c’est une méthode hérité. Ainsi il pourra mieux
nous aider. De plus, cela rend le code plus lisible.

47
Q

int * ptrint1;
std::cout &laquo_space;*ptrint1;

A

pas initialisé, erreur rien au bout du pointeur

48
Q

int * ptrint2 = new int[3];
std::cout &laquo_space;ptrint2[3] &laquo_space;std::endl;

A

erreur, out of bound tableau 3 cases mais acces 4 eme element ?

49
Q

int * ptrint1;
std::couts«ptrintint1;

A

memoire non initilalisé

50
Q

int * ptrint4 = new int[10];
std::cout &laquo_space;*ptrint4 «std::endl;

A

affiche valeur premier element

51
Q

int * ptrint5 = new int[5];
for(int i = 0; i<5; i++){
ptrint5[i]=2*i;
}
std::cout&laquo_space;ptrint5[2] «std::endl;

A

4

52
Q

int * ptrint6 = new int[5];
for(int i = 0; i<5; i++){
ptrint6[i]=2*i;
}
std::cout&laquo_space;*(ptrint5+2) «std::endl;

A

4

53
Q

*ptab++

A

*ptab++ (post-incrémentation)

La valeur pointée par ptab est d'abord accédée.
Ensuite, le pointeur ptab est incrémenté.

Effet :

La valeur retournée est celle de l'emplacement initial.
Le pointeur ptab est modifié après avoir été déréférencé.

Exemple :

cpp
int tab[] = {1, 2, 3, 4, 5};
int *ptab = tab;
cout &laquo_space;*ptab++; // Affiche 1
cout &laquo_space;*ptab; // Affiche 2

54
Q

*++ptab

A

int tab[] = {1, 2, 3, 4, 5};
int *ptab = tab;

cout &laquo_space;*ptab; // Affiche 1
cout &laquo_space;*++ptab; // Affiche 2
cout &laquo_space;*ptab; // Affiche toujours 2
cout &laquo_space;*++ptab; // Affiche 3 *++ptab (pré-incrémentation)

Le pointeur ptab est d'abord incrémenté.
Ensuite, la valeur pointée par le nouveau ptab est accédée.

Effet :

Le pointeur ptab est modifié avant d'être déréférencé.
La valeur retournée est celle du nouvel emplacement pointé.
55
Q

vrai ou faux : pointeurs et references c la meme chose

A

faux, pointeur peut etre nul alors que une reference non, c’est un alias de la variable (varaible elle meme)
un pointeur peut changer de referer, la referance non, c tjrs la meme chose

56
Q
A