Revision sheet: Gestion des tableaux en programmation C++

Plan du Cours

  1. Types structurés mémoire
  2. Tableaux mémoire
  3. Tableaux multidimensionnels
  4. Tableaux encapsulés
  5. Taille non précisée
  6. Pointeurs tableaux
  7. Conversion tableaux-pointeurs
  8. ParamĂštres tableaux fonctions
  9. Retour tableaux fonctions
  10. Allocation dynamique
  11. Libération mémoire
  12. Tableaux dynamiques

1. Types structurés mémoire

Notions clés & Définitions

  • Enregistrement : Collection de champs totalement dĂ©finis Ă  la dĂ©claration, dont l’occupation mĂ©moire est la somme de celle de ses champs, et dont l’adresse correspond Ă  celle du premier champ (voir section 1).
  • Adresse d’un enregistrement : Adresse du premier champ de l’enregistrement, permettant d’accĂ©der Ă  l’ensemble des champs via cette adresse (voir section 1).
  • Tableau : SĂ©quence de taille fixe composĂ©e de cases de type identique, dont l’occupation mĂ©moire est calculĂ©e par la formule taille × taille d’une case, et dont l’adresse correspond Ă  celle de la premiĂšre case (voir section 1).
  • Occupation mĂ©moire d’un enregistrement : Somme des occupations mĂ©moire de tous ses champs, permettant d’évaluer la taille totale en mĂ©moire (voir section 1).
  • Occupation mĂ©moire d’un tableau : Produit de la taille du tableau par la taille d’une case, reprĂ©sentant la mĂ©moire totale occupĂ©e par le tableau (voir section 1).
  • Adresse d’un tableau : Adresse de la premiĂšre case du tableau, utilisĂ©e comme rĂ©fĂ©rence pour accĂ©der aux autres cases par dĂ©calage (voir section 1).

Points essentiels

  • La mĂ©moire d’un enregistrement est calculĂ©e en additionnant la mĂ©moire occupĂ©e par chacun de ses champs, ce qui facilite la gestion de la mĂ©moire lors de l’allocation et de l’accĂšs (voir section 1).
  • La adresse d’un enregistrement ou d’un tableau est celle du premier champ ou de la premiĂšre case, ce qui permet d’accĂ©der Ă  l’ensemble des donnĂ©es via cette rĂ©fĂ©rence.
  • La taille fixe des tableaux garantit une occupation mĂ©moire dĂ©terminĂ©e par la formule taille × taille d’une case, simplifiant la gestion mĂ©moire lors de la dĂ©claration et de l’accĂšs.
  • La distinction entre adresse d’un enregistrement et adresse d’un tableau est essentielle pour la manipulation mĂ©moire, notamment lors de l’utilisation de pointeurs ou d’allocations dynamiques (voir section 1).
  • La comprĂ©hension de ces concepts permet d’optimiser la gestion mĂ©moire dans la programmation algorithmique et en C++, en Ă©vitant les erreurs d’adressage ou de surcharge mĂ©moire.

À retenir

Les enregistrements et tableaux sont des types structurés dont la gestion mémoire repose sur la somme ou le produit de la taille des champs ou cases, avec une adresse de référence correspondant au premier champ ou à la premiÚre case, facilitant leur manipulation et leur allocation.

2. Tableaux mémoire

Notions clés & Définitions

  • Tableau : sĂ©quence contiguĂ« de cases mĂ©moire de mĂȘme type, dont la taille est dĂ©finie lors de la dĂ©claration. Selon XLG2IE011 (2025-2026), il s'agit d'une structure oĂč chaque case est accessible par un indice, et les adresses des cases sont consĂ©cutives en mĂ©moire.

  • Adresse d'un Ă©lĂ©ment tableau : calculĂ©e par la formule adresse de base + indice, oĂč l'adresse de base correspond Ă  celle de la premiĂšre case mĂ©moire du tableau. La formule permet un accĂšs direct Ă  chaque Ă©lĂ©ment par son indice.

  • Occupation mĂ©moire d’un tableau : correspond Ă  la capacitĂ© totale en Ă©lĂ©ments multipliĂ©e par la taille d’un Ă©lĂ©ment, soit nombre d’élĂ©ments × taille Ă©lĂ©ment. Elle reprĂ©sente l’espace mĂ©moire occupĂ© par le tableau en mĂ©moire contiguĂ«.

  • SĂ©quence contiguĂ« : propriĂ©tĂ© essentielle d’un tableau oĂč toutes ses cases mĂ©moire sont alignĂ©es de façon continue, facilitant l’accĂšs par indice et la manipulation efficace en algorithmique.

  • Exemple d’accĂšs et modification par indice : si fou est un tableau de 99 Personnes, alors fou[1] dĂ©signe la premiĂšre case (indice 1), accessible directement, et on peut modifier ses champs comme fou[1].nom ou fou[1].age.

Points essentiels

  • La mĂ©moire d’un tableau est organisĂ©e en une sĂ©quence contiguĂ«, ce qui permet un accĂšs rapide par indice grĂące Ă  la formule d’adresse : adresse_element = adresse_base + indice (voir XLG2IE011, 2025-2026).

  • La taille mĂ©moire d’un tableau est calculĂ©e par nombre d’élĂ©ments × taille d’un Ă©lĂ©ment, ce qui facilite la gestion de l’occupation mĂ©moire et l’allocation.

  • La propriĂ©tĂ© de sĂ©quence contiguĂ« permet d’accĂ©der efficacement Ă  chaque Ă©lĂ©ment par son indice, en utilisant l’arithmĂ©tique de pointeurs : adresse + indice × taille Ă©lĂ©ment.

  • La gestion de l’adresse d’un tableau est simplifiĂ©e par sa nature contiguĂ«, mais il faut faire attention Ă  ne pas dĂ©passer la capacitĂ© allouĂ©e pour Ă©viter des erreurs d’accĂšs.

  • Lors de l’accĂšs Ă  un Ă©lĂ©ment par indice, la formule d’adresse permet de modifier directement la valeur stockĂ©e dans la case mĂ©moire correspondante.

À retenir

Un tableau est une sĂ©quence contiguĂ« de cases mĂ©moire de mĂȘme type, dont l’adresse d’un Ă©lĂ©ment est calculĂ©e par la formule adresse de base + indice, et dont l’occupation mĂ©moire est proportionnelle Ă  sa taille et Ă  son nombre d’élĂ©ments. La propriĂ©tĂ© de contiguĂŻtĂ© facilite un accĂšs rapide et direct Ă  chaque Ă©lĂ©ment par indice.

3. Tableaux multidimensionnels

Notions clés & Définitions

  • Tableau de tableaux : structure composĂ©e de plusieurs tableaux, chaque tableau Ă©tant une dimension supplĂ©mentaire, permettant la reprĂ©sentation multidimensionnelle.
  • Occupation mĂ©moire totale : calculĂ©e comme le produit des dimensions par la taille de l’élĂ©ment, reprĂ©sentant la mĂ©moire nĂ©cessaire pour stocker un tableau multidimensionnel.
  • Adresse d’un Ă©lĂ©ment multidimensionnel : calculĂ©e Ă  partir des indices de chaque dimension, en utilisant une formule qui combine ces indices pour accĂ©der Ă  la position mĂ©moire exacte.
  • Exemple de tableau 2D : un tableau de N1 tableaux, chacun contenant N2 Ă©lĂ©ments, considĂ©rĂ© comme un tableau de tableaux.
  • Tableau 2D : tableau de N1 tableaux de N2 Ă©lĂ©ments, oĂč chaque sous-tableau est accessible par un indice, et l’adresse d’un Ă©lĂ©ment est dĂ©terminĂ©e par la formule d’indexation.

Points essentiels

  • La mĂ©moire occupĂ©e par un tableau multidimensionnel est le produit de toutes ses dimensions multipliĂ© par la taille de l’élĂ©ment, ce qui permet d’estimer l’espace nĂ©cessaire.
  • La reprĂ©sentation en mĂ©moire d’un tableau 2D est un tableau de tableaux, chaque sous-tableau Ă©tant une ligne ou une colonne selon l’orientation choisie.
  • La localisation d’un Ă©lĂ©ment dans un tableau multidimensionnel se calcule en combinant les indices de chaque dimension, en utilisant la formule d’adressage : adresse = adresse de base + somme des indices pondĂ©rĂ©s par leurs tailles respectives.
  • Un tableau 2D peut ĂȘtre vu comme un tableau de N1 tableaux, chacun de N2 Ă©lĂ©ments, permettant une gestion flexible et modulaire des donnĂ©es.
  • La gestion de l’adresse d’un Ă©lĂ©ment dans un tableau multidimensionnel repose sur la formule d’indexation, qui permet de passer d’un accĂšs logique Ă  une adresse mĂ©moire physique.

À retenir

Les tableaux multidimensionnels sont des structures composĂ©es de tableaux de tableaux, dont l’adresse d’un Ă©lĂ©ment se calcule Ă  partir des indices en utilisant une formule d’adressage spĂ©cifique, et leur occupation mĂ©moire est proportionnelle au produit de leurs dimensions.

4. Tableaux encapsulés

Notions clés & Définitions

  • Tableau encapsulĂ© : Enregistrement contenant un tableau, sa capacitĂ© et son occupation, permettant une gestion dynamique.
    Christophe Jermann (2025-2026) : structure qui stocke un tableau avec ses paramĂštres pour une gestion efficace de tableaux partiellement remplis.

  • CapacitĂ© : Nombre total d’élĂ©ments que peut contenir le tableau encapsulĂ©, stockĂ© dans le champ capacitĂ©.
    Christophe Jermann (2025-2026) : limite maximale du tableau, dĂ©finie lors de l’allocation ou de la rĂ©allocation.

  • Occupation : Nombre d’élĂ©ments actuellement utilisĂ©s dans le tableau encapsulĂ©, stockĂ© dans le champ occupation.
    Christophe Jermann (2025-2026) : indicateur du nombre d’élĂ©ments remplis, utilisĂ© pour la gestion dynamique.

  • Stockage de la capacitĂ© et occupation pour gestion dynamique : technique consistant Ă  suivre en permanence ces deux paramĂštres pour ajuster la taille du tableau selon l’utilisation rĂ©elle.
    Christophe Jermann (2025-2026) : principe fondamental pour la gestion efficace de tableaux partiellement remplis.

Points essentiels

  • Le tableau encapsulĂ© est une structure d’enregistrement comprenant au minimum trois champs : data (le tableau), capacitĂ© (taille maximale) et occupation (nombre d’élĂ©ments utilisĂ©s).
  • La gestion dynamique repose sur la mise Ă  jour de ces deux paramĂštres (capacitĂ© et occupation) pour Ă©viter la surcharge ou le gaspillage mĂ©moire.
  • La structure permet de manipuler efficacement des tableaux partiellement remplis en Ă©vitant la rĂ©allocation constante ou le dĂ©passement de capacitĂ©.
  • La capacitĂ© est gĂ©nĂ©ralement fixĂ©e lors de l’allocation initiale ou lors d’une rĂ©allocation, tandis que l’occupation Ă©volue au fil des insertions ou suppressions.
  • Exemple de structure :
    type TabEncapsulé = Enregistrement
        data : Tableau de Réels
        capacité : Entier
        occupation : Entier
    Fin Enregistrement
    
  • La gestion de la capacitĂ© et de l’occupation permet d’implĂ©menter des opĂ©rations telles que l’ajout, la suppression ou la rĂ©allocation de maniĂšre efficace.

À retenir

Le tableau encapsulĂ© combine stockage et gestion dynamique, en utilisant les champs capacitĂ© et occupation pour optimiser l’utilisation mĂ©moire lors de manipulations partielles.

5. Taille non précisée

Notions clés & Définitions

  • Tableau de taille non prĂ©cisĂ©e : tableau dont la taille n’est pas indiquĂ©e lors de la dĂ©claration, mais qui peut ĂȘtre utilisĂ© via des pointeurs ou paramĂštres de fonction (voir section 8). La taille est alors dĂ©terminĂ©e dynamiquement ou lors de l’allocation, sans ĂȘtre explicitement connue dans la dĂ©claration.

  • ParamĂštres de fonction : paramĂštres dĂ©clarĂ©s sans taille prĂ©cise, par exemple void f(double tab[]), permettant l’utilisation de tableaux de taille variable ou inconnue. La taille est gĂ©nĂ©ralement omise car elle est dĂ©jĂ  connue dans l’appelant (voir section 8).

  • Pointeurs : variables stockant l’adresse d’un tableau ou d’un Ă©lĂ©ment, permettant de manipuler des tableaux de taille indĂ©finie ou dynamique. Lorsqu’un tableau est converti en pointeur (dĂ©gradation), la taille n’est pas accessible via sizeof (voir section 7).

  • GĂ©nĂ©ricitĂ© des sous-algorithmes : capacitĂ© Ă  Ă©crire des algorithmes ou fonctions qui manipulent des tableaux de tailles diffĂ©rentes sans spĂ©cifier explicitement la taille, grĂące Ă  l’utilisation de paramĂštres de type tableau non prĂ©cisĂ©s ou de pointeurs (voir section 8).

  • sizeof : opĂ©rateur qui retourne la taille en octets d’un tableau en mĂ©moire, ne fonctionne pas pour un tableau passĂ© en paramĂštre sous forme de pointeur ou de tableau de taille non prĂ©cisĂ©e, car l’information de taille est perdue lors de la dĂ©gradation (voir section 1 et 7).

Points essentiels

  • La dĂ©claration d’un tableau sans taille prĂ©cise est interdite sauf pour certains cas : paramĂštres de fonction et pointeurs. En effet, pour un paramĂštre TYPE tab[], la taille est omise car elle est implicite dans l’appel, permettant ainsi la gĂ©nĂ©ricitĂ© des sous-algorithmes (voir section 8).

  • La taille d’un tableau non prĂ©cisĂ©e ne peut pas ĂȘtre dĂ©terminĂ©e par sizeof car, lors de la dĂ©gradation en pointeur, l’information sur la taille est perdue. La seule façon de connaĂźtre la taille est de la gĂ©rer explicitement via des variables ou des paramĂštres (voir section 7).

  • En C++, la syntaxe void f(double tab[]) est Ă©quivalente Ă  void f(double* tab), ce qui montre que la taille n’est pas conservĂ©e dans la dĂ©claration. La gestion de la taille doit donc ĂȘtre assurĂ©e par des variables ou des conventions dans le code.

  • La gĂ©nĂ©ricitĂ© permet d’écrire des sous-algorithmes qui manipulent des tableaux de tailles diffĂ©rentes, en utilisant des paramĂštres de type tableau non prĂ©cisĂ©s ou des pointeurs, et en utilisant une opĂ©ration pour obtenir la taille lors de l’utilisation (voir section 8).

  • La gestion dynamique de la taille via allocation et rĂ©allocation permet d’adapter la capacitĂ© du tableau Ă  l’utilisation rĂ©elle, Ă©vitant ainsi le gaspillage mĂ©moire ou la perte de donnĂ©es (voir section 4 et 28).

À retenir

Les tableaux de taille non prĂ©cisĂ©e offrent une flexibilitĂ© essentielle en algorithmique et en programmation, mais nĂ©cessitent une gestion explicite de la taille, notamment lors de l’allocation, de la manipulation et de la libĂ©ration mĂ©moire, en raison de la perte d’information lors de la conversion en pointeur.

6. Pointeurs tableaux

Notions clés & Définitions

  • Adresse du premier Ă©lĂ©ment : L'adresse mĂ©moire du dĂ©but d'un tableau, accessible via un pointeur vers tableau ou par dĂ©gradation automatique (array-to-pointer decay) en C++. Selon PERROUX (date), cette adresse permet d’accĂ©der Ă  l’ensemble des Ă©lĂ©ments du tableau en utilisant l’arithmĂ©tique des pointeurs.

  • DĂ©rĂ©fĂ©rencement d’un pointeur vers tableau : OpĂ©ration consistant Ă  accĂ©der au tableau pointĂ© par un pointeur en utilisant l’opĂ©rateur *. Cela donne accĂšs Ă  l’ensemble du tableau, permettant d’utiliser des opĂ©rations comme la taille ou l’accĂšs par indice. En C++, *p dĂ©signe le tableau pointĂ©, et *p[i] l’élĂ©ment d’indice i.

  • OpĂ©rations possibles :

    • Taille : La taille d’un tableau pointĂ© peut ĂȘtre obtenue via une opĂ©ration spĂ©cifique (ex. taille(tab) ou |tab|), mais la taille n’est pas directement accessible via le pointeur seul.
    • AccĂšs par indice : Utilisation de la notation mĂ©moire(p)[i] ou *(p + i) pour accĂ©der Ă  l’élĂ©ment d’indice i.
    • Passage en paramĂštre : Un tableau peut ĂȘtre passĂ© Ă  une fonction via un pointeur, permettant d’accĂ©der et de modifier ses Ă©lĂ©ments. La diffĂ©rence entre affectation d’adresse (p = &tab[0]) et affectation de tableau (p = tab) est essentielle : la premiĂšre affecte l’adresse du premier Ă©lĂ©ment, la seconde rĂ©alise une dĂ©gradation automatique du tableau en pointeur.
  • DiffĂ©rence entre affectation d’adresse et affectation de tableau :

    • Affectation d’adresse (p = &tab[0]) : affecte Ă  p l’adresse du premier Ă©lĂ©ment du tableau.
    • Affectation de tableau (p = tab) : en C++, cette opĂ©ration est une dĂ©gradation automatique du tableau en pointeur vers son premier Ă©lĂ©ment, mais ne copie pas le tableau. La distinction est importante pour la gestion mĂ©moire et la sĂ©curitĂ©.
    • Note : La dĂ©gradation (array-to-pointer decay) entraĂźne la perte d’information sur la taille du tableau, ce qui doit ĂȘtre prĂ©cisĂ© par d’autres moyens (ex. |tab|).

Points essentiels

  • Un pointeur vers tableau est souvent dĂ©clarĂ© comme type *pTab, oĂč pTab pointe vers la premiĂšre case du tableau. La dĂ©gradation automatique en C++ permet d’utiliser un tableau comme un pointeur vers son premier Ă©lĂ©ment, mais la taille du tableau n’est pas conservĂ©e dans le pointeur seul, ce qui limite certaines opĂ©rations.

  • La diffĂ©rence entre affectation d’adresse (p = &tab[0]) et affectation de tableau (p = tab) est cruciale : la premiĂšre concerne une affectation explicite d’adresse, la seconde une dĂ©gradation automatique du tableau en pointeur.

  • La gestion des opĂ©rations sur un pointeur vers tableau inclut la taille du tableau, accessible via une opĂ©ration spĂ©cifique, et l’accĂšs aux Ă©lĂ©ments par indice ou arithmĂ©tique de pointeurs. La taille du tableau n’étant pas stockĂ©e dans le pointeur, il faut la gĂ©rer sĂ©parĂ©ment (ex. |tab|).

  • La conversion automatique d’un tableau en pointeur (array-to-pointer decay) permet d’utiliser le tableau comme un pointeur, mais entraĂźne la perte d’informations sur la taille, ce qui doit ĂȘtre explicitement gĂ©rĂ© pour Ă©viter les erreurs.

À retenir

Un pointeur vers tableau en C++ dĂ©signe l’adresse du premier Ă©lĂ©ment, mais la distinction entre affectation d’adresse et dĂ©gradation automatique est essentielle pour une gestion correcte de la mĂ©moire et des opĂ©rations sur les tableaux. La taille du tableau doit ĂȘtre conservĂ©e sĂ©parĂ©ment, car elle n’est pas implicite dans le pointeur.

7. Conversion tableaux-pointeurs

Notions clés & Définitions

  • DĂ©gradation de tableau en pointeur (array-to-pointer decay) : en C++, lorsqu’un tableau est utilisĂ© dans une expression, il est automatiquement converti en pointeur vers son premier Ă©lĂ©ment, ce qui entraĂźne la perte d’information sur la taille du tableau. (source : Christophe Jermann, 2025-2026)

  • *ÉgalitĂ©s tab == &tab[0] et tab == tab[0] : en raison de la dĂ©gradation, un tableau tab est Ă©quivalent Ă  l’adresse de sa premiĂšre case (&tab[0]), et le dĂ©rĂ©fĂ©rencement *tab donne la valeur du premier Ă©lĂ©ment. (source : Christophe Jermann, 2025-2026)

  • Pointeur vers type Ă©lĂ©ment, pas vers tableau : en C++, un pointeur dĂ©clarĂ© comme int* p pointe vers un seul Ă©lĂ©ment de type int, et non vers un tableau complet. La conversion automatique ne permet pas de dĂ©clarer un pointeur spĂ©cifique Ă  un tableau, mais uniquement vers le type des Ă©lĂ©ments. (source : Christophe Jermann, 2025-2026)

Points essentiels

  • Lorsqu’un tableau est utilisĂ© dans une expression, il est converti en pointeur vers son premier Ă©lĂ©ment, ce qui simplifie l’accĂšs mais entraĂźne la perte d’information sur la taille du tableau (d’oĂč le terme "decay"). Cette conversion est automatique en C++ : "array-to-pointer decay".

  • La conversion implique que tab (tableau) et &tab[0] (adresse de la premiĂšre case) sont Ă©quivalents, et que *tab (dĂ©rĂ©fĂ©rencement) correspond Ă  la valeur du premier Ă©lĂ©ment. Cependant, il ne faut pas confondre un pointeur vers un seul Ă©lĂ©ment et un pointeur vers un tableau, car le pointeur ne contient pas d’information sur la taille du tableau.

  • La dĂ©claration d’un pointeur vers un tableau de taille fixe doit se faire explicitement, par exemple int (*p)[N], pour Ă©viter toute ambiguĂŻtĂ©. La conversion automatique ne s’applique qu’aux tableaux de taille non prĂ©cisĂ©e ou dans le contexte d’une dĂ©gradation implicite.

  • La vigilance est essentielle lors de l’utilisation de tableaux et pointeurs en C++, car cette dĂ©gradation peut conduire Ă  des erreurs subtiles, notamment lors de passages en paramĂštre ou d’affectations, d’oĂč l’importance de commentaires explicatifs pour clarifier le rĂŽle de chaque variable.

À retenir

En C++, un tableau se convertit automatiquement en pointeur vers son premier Ă©lĂ©ment, mais cette opĂ©ration entraĂźne la perte d’information sur sa taille. La comprĂ©hension de cette dĂ©gradation est cruciale pour Ă©viter les erreurs lors de la manipulation de tableaux et pointeurs.

8. ParamĂštres tableaux fonctions

Notions clés & Définitions

  • Passage par rĂ©fĂ©rence Ă  tableau de taille fixe : syntaxe permettant de transmettre un tableau d’une taille prĂ©cise Ă  une fonction sans decay, en utilisant la rĂ©fĂ©rence Ă  un tableau de taille N, par exemple : void f(const int (&t)[3]). Cela Ă©vite la perte d’information sur la taille du tableau lors de l’appel.

  • Decay (dĂ©grader un tableau en pointeur) : conversion automatique en C++ oĂč un tableau passĂ© en paramĂštre est traitĂ© comme un pointeur vers son premier Ă©lĂ©ment, par exemple : void g(int p[]). Cela entraĂźne la perte d’informations sur la taille du tableau.

  • Passage de tableau en paramĂštre avec const et rĂ©fĂ©rence : syntaxe recommandĂ©e pour passer un tableau en lecture seule tout en conservant sa taille, par exemple : void f(const int (&t)[N]). Elle Ă©vite le decay et garantit la taille lors de l’appel.

  • Exemple de syntaxe correcte pour Ă©viter decay : void f(const int (&t)[N]) pour un tableau de taille N en entrĂ©e, permettant d’accĂ©der Ă  la taille via N et d’éviter la conversion implicite en pointeur.

  • DiffĂ©rence entre passage par rĂ©fĂ©rence et passage par pointeur : le passage par rĂ©fĂ©rence Ă  un tableau de taille fixe conserve la taille du tableau et empĂȘche le decay, tandis que le passage par pointeur (int p[]) ou int* p ne conserve pas cette information, ce qui peut compliquer la gestion de la taille dans la fonction.

Points essentiels

  • La syntaxe void f(const int (&t)[N]) permet de passer un tableau de taille N par rĂ©fĂ©rence, Ă©vitant ainsi le decay, et garantit que la taille est connue dans la fonction. Elle est particuliĂšrement utile pour des tableaux de taille fixe, notamment dans les algorithmes oĂč la taille doit ĂȘtre conservĂ©e.

  • Le passage par pointeur (int p[] ou int* p) entraĂźne un decay automatique du tableau, ce qui signifie que la fonction ne connaĂźt plus la taille du tableau passĂ©, sauf si celle-ci est transmise sĂ©parĂ©ment ou si la taille est dĂ©terminĂ©e par d’autres moyens.

  • La diffĂ©rence fondamentale rĂ©side dans la conservation ou non de la taille du tableau lors de la transmission Ă  une fonction. La rĂ©fĂ©rence Ă  tableau fixe (&t[N]) permet de prĂ©server cette information, contrairement au pointeur.

  • La syntaxe const int (&t)[N] est recommandĂ©e pour les paramĂštres en lecture seule, pour Ă©viter la modification accidentelle et pour garantir la taille du tableau dans la fonction.

  • La conversion automatique (decay) d’un tableau en pointeur est une opĂ©ration implicite qui peut entraĂźner des erreurs si la taille du tableau n’est pas explicitement gĂ©rĂ©e.

À retenir

Pour passer un tableau en paramĂštre sans perdre d’informations sur sa taille, il faut utiliser la syntaxe void f(const int (&t)[N]), qui Ă©vite le decay et garantit la connaissance de la taille dans la fonction. Le passage par pointeur (int p[]) ne conserve pas cette information, ce qui peut compliquer la gestion dans les algorithmes.

9. Retour tableaux fonctions

Notions clés & Définitions

  • Impossible de retourner un tableau directement en C++ : en C++, la syntaxe TYPE[N] pour le retour de fonction n’est pas autorisĂ©e, car cela impliquerait de retourner un tableau par valeur, ce qui est interdit. La solution consiste Ă  retourner un pointeur vers le tableau (type TYPE*), ce qui entraĂźne des risques liĂ©s Ă  la gestion de la mĂ©moire et Ă  la durĂ©e de vie des variables (voir CRITIQUE).
  • Fonction retournant un pointeur vers tableau : en C++, une fonction peut retourner un pointeur (TYPE*) pointant vers un tableau allouĂ© dynamiquement ou existant en mĂ©moire, mais cela ne garantit pas la sĂ©curitĂ© si la mĂ©moire est locale ou dĂ©sallouĂ©e (voir CRITIQUE).
  • Risques liĂ©s au retour de pointeur sur variable locale : si une fonction retourne un pointeur vers une variable locale (par exemple, un tableau local), la mĂ©moire sera dĂ©sallouĂ©e Ă  la sortie de la fonction, rendant le pointeur invalide et provoquant des comportements indĂ©finis (voir CRITIQUE).
  • Convention : utiliser procĂ©dures avec tableaux en sortie : pour Ă©viter ces risques, il est recommandĂ© d’utiliser des procĂ©dures (ou sous-algorithmes) qui prennent en paramĂštre un tableau en sortie, souvent avec des prĂ©conditions sur la capacitĂ© du tableau, afin de gĂ©rer explicitement la mĂ©moire et la capacitĂ© (voir CRITIQUE).
  • PrĂ©conditions sur capacitĂ© des tableaux en sortie : lors de l’utilisation de procĂ©dures pour retourner des donnĂ©es dans un tableau, il est essentiel de garantir que la capacitĂ© du tableau en sortie est suffisante pour contenir toutes les donnĂ©es, afin d’éviter les dĂ©passements ou pertes de donnĂ©es (voir CRITIQUE).

Points essentiels

  • En C++, il est impossible de retourner directement un tableau dans une fonction, car la syntaxe TYPE[N] n’est pas autorisĂ©e pour le retour. La pratique recommandĂ©e est d’utiliser un pointeur vers tableau (TYPE)* ou une structure encapsulant le tableau, mais cela comporte des risques liĂ©s Ă  la gestion mĂ©moire (voir CRITIQUE).
  • La conversion implicite d’un tableau en pointeur (dĂ©cay) entraĂźne une perte d’information sur la taille du tableau, rendant difficile la gestion de la capacitĂ© et la sĂ©curitĂ© lors de l’utilisation du pointeur retournĂ© (voir CRITIQUE).
  • La convention en algorithmique et en C++ est de ne pas faire retourner directement un tableau dans une fonction, mais d’utiliser des procĂ©dures avec tableaux en sortie, en imposant des prĂ©conditions sur la capacitĂ© pour assurer la cohĂ©rence (voir CRITIQUE).
  • Lorsqu’on retourne un tableau via un pointeur, il faut faire attention Ă  la durĂ©e de vie de la mĂ©moire : si le tableau est local Ă  la fonction, il sera dĂ©sallouĂ© Ă  la sortie, ce qui rend le pointeur invalide (voir CRITIQUE).
  • La gestion dynamique des tableaux (allocation, rĂ©allocation, libĂ©ration) permet d’adapter la taille du tableau Ă  l’utilisation rĂ©elle, mais nĂ©cessite une gestion rigoureuse pour Ă©viter les fuites mĂ©moire ou erreurs d’accĂšs (voir CRITIQUE).

À retenir

En C++, il est interdit de retourner un tableau directement dans une fonction ; il faut privilĂ©gier l’utilisation de procĂ©dures avec tableaux en sortie ou de pointeurs vers tableaux allouĂ©s dynamiquement, en respectant strictement la gestion mĂ©moire pour garantir la sĂ©curitĂ© et la cohĂ©rence du programme.

10. Allocation dynamique

Notions clés & Définitions

  • Allocation dynamique : Technique permettant de rĂ©server de la mĂ©moire Ă  l'exĂ©cution selon le besoin rĂ©el, en dimensionnant la structure lors de l'exĂ©cution (voir section 3).
  • Utilisation de pointeurs pour stocker l'adresse : Les pointeurs contiennent l'adresse du dĂ©but du tableau allouĂ©, permettant d'accĂ©der et de manipuler la mĂ©moire allouĂ©e (voir section 6).
  • Allocation avec new[] en C++ : OpĂ©ration d'allocation de mĂ©moire pour un tableau de taille variable en C++, utilisant l'instruction new[] pour rĂ©server dynamiquement un espace mĂ©moire contigu (voir section 12).
  • NĂ©cessitĂ© de dĂ©sallocation : AprĂšs utilisation, il est impĂ©ratif de libĂ©rer la mĂ©moire allouĂ©e avec delete[] pour Ă©viter les fuites mĂ©moire, en rĂ©initialisant le pointeur Ă  nullptr (voir section 11).
  • Exemple d'allocation : Allocation d’un tableau de taille saisie par l’utilisateur, par exemple pNotes = new double[taille];, puis dĂ©sallocation avec delete[] pNotes;.

Points essentiels

L’allocation dynamique rĂ©pond Ă  la problĂ©matique de taille inconnue au moment de la programmation, permettant d’ajuster la mĂ©moire Ă  la taille rĂ©elle des donnĂ©es (voir section 3). En C++, la mĂ©canique repose sur l’utilisation de new[] pour rĂ©server et delete[] pour libĂ©rer la mĂ©moire, en respectant la rĂšgle d’association : new[] doit toujours ĂȘtre suivi de delete[]. La gestion de tableaux multidimensionnels se fait par allocation successives de pointeurs vers pointeurs, en libĂ©rant chaque sous-tableau avant de libĂ©rer le tableau principal (voir section 24). La libĂ©ration est cruciale pour Ă©viter les fuites mĂ©moire, et il est conseillĂ© de rĂ©initialiser les pointeurs Ă  nullptr aprĂšs dĂ©sallocation (voir section 11). La gestion d’un tableau dynamique inclut aussi la rĂ©allocation pour ajuster la capacitĂ© lors de l’ajout ou retrait de donnĂ©es, en recopiant les donnĂ©es dans un nouveau tableau plus adaptĂ©, puis en libĂ©rant l’ancien (voir section 29). La bibliothĂšque standard C++ propose Ă©galement le type vector<T> pour gĂ©rer automatiquement ces opĂ©rations, avec des stratĂ©gies de redimensionnement intĂ©grĂ©es (voir section 34).

À retenir

L’allocation dynamique permet de dimensionner prĂ©cisĂ©ment la mĂ©moire nĂ©cessaire Ă  l’exĂ©cution, mais exige une gestion rigoureuse pour libĂ©rer la mĂ©moire et Ă©viter les fuites, notamment via new[] et delete[] en C++.

11. Libération mémoire

Notions clés & Définitions

  • LibĂ©ration mĂ©moire avec delete[] : opĂ©ration en C++ permettant de dĂ©sallouer la mĂ©moire allouĂ©e dynamiquement Ă  un tableau avec new[]. Elle doit obligatoirement ĂȘtre associĂ©e Ă  une allocation avec new[] pour Ă©viter les fuites mĂ©moire.
  • Correspondance new[] ↔ delete[] : rĂšgle fondamentale en C++ : chaque nouvelle allocation avec new[] doit ĂȘtre suivie d'une dĂ©sallocation avec delete[] pour assurer la gestion correcte de la mĂ©moire.
  • RĂ©initialisation des pointeurs inutilisĂ©s Ă  nullptr : pratique recommandĂ©e pour Ă©viter les pointeurs pendants (dangling pointers), en leur assignant la valeur nullptr aprĂšs libĂ©ration, ce qui facilite la dĂ©tection d’accĂšs Ă  une mĂ©moire dĂ©sallouĂ©e.
  • LibĂ©ration mĂ©moire pour tableaux multidimensionnels allouĂ©s dynamiquement : processus spĂ©cifique en C++ pour libĂ©rer une matrice 2D ou plus, allouĂ©e par pointeurs imbriquĂ©s, en libĂ©rant d’abord chaque sous-tableau puis le tableau principal. Exemple : libĂ©ration d’une matrice 2D allouĂ©e par pointeurs de pointeurs.
  • Exemple de libĂ©ration matrice 2D : pour une matrice allouĂ©e dynamiquement en C++, il faut faire un delete[] sur chaque sous-tableau, puis sur le tableau principal, pour Ă©viter les fuites mĂ©moire et respecter la correspondance new[] / delete[].

Points essentiels

  • La gestion de la mĂ©moire dynamique en C++ repose sur l’utilisation stricte de new[] pour l’allocation et delete[] pour la dĂ©sallocation, afin d’éviter les fuites mĂ©moire et les comportements indĂ©finis.
  • La rĂšgle new[] ↔ delete[] est impĂ©rative : utiliser delete[] sur un tableau allouĂ© avec new[], et non delete seul, qui est rĂ©servĂ© Ă  la dĂ©sallocation d’un seul objet.
  • AprĂšs libĂ©ration, il est conseillĂ© de rĂ©initialiser le pointeur Ă  nullptr pour Ă©viter des accĂšs accidentels Ă  une mĂ©moire libĂ©rĂ©e, ce qui pourrait provoquer des erreurs difficiles Ă  diagnostiquer.
  • La libĂ©ration d’un tableau multidimensionnel allouĂ© dynamiquement doit suivre une procĂ©dure prĂ©cise : libĂ©rer chaque sous-tableau avec delete[] puis le tableau principal, pour assurer une gestion correcte de la mĂ©moire.
  • Exemple pratique : pour une matrice 2D allouĂ©e par pointeurs imbriquĂ©s, il faut d’abord libĂ©rer chaque ligne, puis le tableau de pointeurs.

À retenir

La libĂ©ration correcte de la mĂ©moire dynamique en C++ repose sur l’utilisation stricte de delete[] en correspondance avec new[], accompagnĂ©e de la rĂ©initialisation des pointeurs Ă  nullptr pour garantir la sĂ©curitĂ© et l’efficacitĂ© de la gestion mĂ©moire.

12. Tableaux dynamiques

Notions clés & Définitions

  • Tableaux encapsulĂ©s : structures de stockage contenant un tableau, sa capacitĂ© et son occupation, permettant la gestion dynamique de la mĂ©moire (voir section 4).
  • Gestion automatique de capacitĂ© et occupation : mĂ©canisme qui ajuste la taille d’un tableau en fonction de son taux de remplissage, pour optimiser mĂ©moire et performance (voir slide 32).
  • RĂ©allocation pour ajuster la taille : opĂ©ration consistant Ă  allouer un nouveau tableau de taille modifiĂ©e, recopier les donnĂ©es de l’ancien, puis libĂ©rer l’ancien (voir slides 29-31).
  • Tableaux de taille non prĂ©cisĂ©e : tableaux dont la taille n’est pas fixĂ©e Ă  la dĂ©claration, permettant une plus grande flexibilitĂ© dans la gestion dynamique (voir slide 8).
  • Pointeurs vers tableaux : adresses de tableaux allouĂ©s dynamiquement, permettant leur manipulation via des opĂ©rations de dĂ©rĂ©fĂ©rencement et de gestion mĂ©moire (voir slides 11-13).

Points essentiels

  • La gestion d’un tableau dynamique repose sur la capacitĂ© Ă  ajuster sa taille en fonction de l’occupation, en utilisant la rĂ©allocation (allocation, copie, libĂ©ration).
  • La stratĂ©gie de rĂ©allocation doit prendre en compte le taux de remplissage (occupation / capacitĂ©) et des paramĂštres comme les facteurs d’agrandissement ou de rĂ©duction pour optimiser performance et mĂ©moire.
  • La mĂ©canique d’allocation/dĂ©sallocation en C++ utilise new[] et delete[], et doit respecter la rĂšgle d’équivalence pour Ă©viter fuite mĂ©moire ou erreurs (voir slides 22-25).
  • La gestion d’un tableau dynamique doit ĂȘtre accompagnĂ©e de sous-algorithmes spĂ©cifiques pour l’allocation et la libĂ©ration, notamment pour les tableaux multidimensionnels.
  • La bibliothĂšque standard C++ propose le type vector<T> pour simplifier la gestion automatique des tableaux dynamiques, avec des performances garanties selon la complexitĂ© asymptotique.

À retenir

Les tableaux dynamiques permettent de gĂ©rer efficacement des structures de donnĂ©es dont la taille varie durant l’exĂ©cution, en utilisant la rĂ©allocation contrĂŽlĂ©e pour optimiser mĂ©moire et performance.

Tableaux de SynthĂšse

ThÚmeDéfinition / CaractéristiquesAuteur / Référence
EnregistrementCollection de champs, adresse du premier champ, occupation mĂ©moire = somme des champs—
TableauSĂ©quence fixe de cases de mĂȘme type, adresse de la premiĂšre case, occupation mĂ©moire = taille × taille d’une case—
Tableau multidimensionnelStructure de tableaux de tableaux, adresse calculĂ©e via indices, occupation mĂ©moire = produit des dimensions × taille d’un Ă©lĂ©ment—
Tableau encapsuléEnregistrement avec tableau, capacité, occupation, gestion dynamique (Jermann, 2025-2026)Christophe Jermann (2025-2026)
Allocation dynamiqueRĂ©servation mĂ©moire Ă  l’exĂ©cution, gestion flexible de la taille—
LibĂ©ration mĂ©moireDĂ©sallocation mĂ©moire pour Ă©viter fuite, libĂ©rer la mĂ©moire allouĂ©e dynamiquement—

PiÚges & Confusions Fréquentes

  1. Confondre l’adresse d’un enregistrement et celle d’un tableau (premier champ vs premiùre case).
  2. Oublier que la taille d’un tableau est fixe lors de la dĂ©claration, ce qui peut causer des dĂ©passements.
  3. Confondre la formule d’adresse d’un tableau unidimensionnel avec celle d’un tableau multidimensionnel.
  4. NĂ©gliger la propriĂ©tĂ© de mĂ©moire contiguĂ« d’un tableau, menant Ă  des erreurs d’accĂšs ou de manipulation.
  5. Mal calculer l’occupation mĂ©moire en ne tenant pas compte de la taille de chaque Ă©lĂ©ment.
  6. Confondre la gestion mĂ©moire statique et dynamique, notamment lors de l’allocation ou libĂ©ration.
  7. Omettre de vĂ©rifier la capacitĂ© lors de l’utilisation de tableaux encapsulĂ©s ou dynamiques.

Checklist Examen

  1. ConnaĂźtre la dĂ©finition d’un enregistrement et son adresse selon la section 1.
  2. Savoir calculer l’occupation mĂ©moire d’un tableau fixe en utilisant la formule taille × nombre d’élĂ©ments.
  3. Expliquer la diffĂ©rence entre adresse d’un tableau et adresse d’un enregistrement.
  4. MaĂźtriser la formule d’adressage d’un tableau unidimensionnel : adresse = adresse de base + indice × taille d’un Ă©lĂ©ment.
  5. DĂ©crire la reprĂ©sentation mĂ©moire d’un tableau multidimensionnel et la formule pour accĂ©der Ă  un Ă©lĂ©ment.
  6. Savoir que la mĂ©moire d’un tableau multidimensionnel est le produit de ses dimensions × taille d’un Ă©lĂ©ment.
  7. ConnaĂźtre la structure d’un tableau encapsulĂ© selon Christophe Jermann (2025-2026).
  8. Comprendre la gestion dynamique de tableaux avec allocation et libération mémoire.
  9. Savoir différencier allocation statique et dynamique, et leurs implications.
  10. Maßtriser la gestion mémoire pour éviter fuite ou surcharge.
  11. Connaütre la formule d’adresse pour un tableau multidimensionnel.
  12. VĂ©rifier la capacitĂ© lors de l’utilisation de tableaux encapsulĂ©s ou dynamiques.

Test your knowledge

Test your knowledge on Gestion des tableaux en programmation C++ with 12 multiple-choice questions with detailed corrections.

1. Qu'est-ce qu'un type structuré mémoire ?

2. Quel auteur a travaillé sur la notion de tableaux encapsulés durant l'année 2025-2026 ?

Take the quiz →

Review with flashcards

Memorize the key concepts of Gestion des tableaux en programmation C++ with 24 interactive flashcards.

Types structurĂ©s mĂ©moire — dĂ©finitions ?

Enregistrement, tableau, multidimensionnel, encapsulé.

Enregistrement — adresse ?

Adresse du premier champ.

Tableau — occupation mĂ©moire ?

Taille × taille d’une case.

See flashcards →

Similar courses

Create your own revision sheets

Import your course and AI generates sheets, quizzes and flashcards in 30 seconds.

Sheet generator