Skip to content
Snippets Groups Projects
Commit 2f83d210 authored by orestis.malaspin's avatar orestis.malaspin
Browse files

ajout smart pointers

parent 5660c215
No related branches found
No related tags found
No related merge requests found
Pipeline #
...@@ -20,6 +20,7 @@ sansfont: Sans Serif ...@@ -20,6 +20,7 @@ sansfont: Sans Serif
- [4.1 Commentaires](commentaires.html). - [4.1 Commentaires](commentaires.html).
- [4.2 Gestion d'erreurs](errors.html). - [4.2 Gestion d'erreurs](errors.html).
- [6.1 Méthodes](methods.html). - [6.1 Méthodes](methods.html).
- [6.2 Pointeurs intelligents](smart_pointers.html).
- [6.2 Collections: String, Vector, HashMap](collections.html). - [6.2 Collections: String, Vector, HashMap](collections.html).
- [7.1 Tests](tests.html). - [7.1 Tests](tests.html).
- [8.1 Itérateurs](iterators.html). - [8.1 Itérateurs](iterators.html).
......
---
title: Cours de programmation séquentielle
subtitle: Pointeurs intelligents
author: Orestis Malaspinas
sansfont: Sans Serif
---
# Pointeurs
## Généralités
- Un **pointeur** est une variable qui contient une adresse mémoire.
- Cette adresse **pointe** vers des données.
![Illustration: tableau.](figs/mem_ref_vec.svg){width=50%}
- Question: Quel type de pointeur avons-nous déjà rencontré?
- Réponse: La référence.
## Smart pointers
- Un **pointeur intelligent** est un type abstrait qui rajoute des fonctionnalités au poiteur standard.
- Management automatique de la mémoire.
- Vérification de limites.
- En particulier, ils permettent la désallocation de la mémoire de manière automatique:
- On peut avoir plusieurs pointeurs sur un espace mémoire.
- Quand le dernier pointeurs est détruit, l'espace mémoire est désalloué.
- Permet d'empêcher les fuites mémoires.
- Il existe différents types:
- Un poiteur unique est le propriétaire de ses données (quand il est détruit les données aussi).
- On compte le nombre de références sur des données, quand ce nombre tombe à zéro on détruit tout.
## En Rust
- Exemples:
- `Vec<T>`{.rust}, `String`{.rust}: ces types possèdent de la mémoire et la manipule eux-mêmes.
- Les pointeurs intelligent doivent implémenter deux traits:
- `Deref`{.ruist}: comment on déréférence le pointeur.
- `Drop`{.rust}: comment on détruit le pointeur.
- Les trois cas les plus typiques (il y en a d'autres):
- `Box<T>`{.rust} pointeur unique qui alloue des données sur la pile.
- `Rc<T>`{.rust} "reference counted" type, qui permet de partager la propriété.
- `Ref<T>`{.rust} et `RefMut<T>`{.rust} qui permet d'imposer les règles de propriété à l'exécution plutôt qu'à la compilation.
# Le type `Box<T>`{.rust}
## Généralités
- Utile pour stocker des données sur le tas.
- La seule chose stockée sur la pile est le pointeur sur les données du tas.
- Cas typiques d'utilisation:
- Quand la taille d'un type est inconnu à la compilation.
- Quand on veut transférer la propriété de grandes quantité de données mais s'assurer que les données ne seront pas copiées (juste le pointeur).
## Utilisation
<pre><code data-trim="hljs rust" class="lang-rust">
fn main()
{
let num = Box::new(10);
println!("num = {}", num); // déréférenciation automatique
println!("num = {}", *num); // déréférenciation explicite
let x = 10;
// seule la déréférenciation explicite marche
println!("Is {} equal to {}?. Answer: {}", num, x, *num == x);
let y = &x;
// La seule différence est qu'ici nous avons une référence
println!("Is {} equal to {}?. Answer: {}", y, x, *y == x);
}
</code></pre>
- Dans l'appel de fonctions/méthodes la déréférenciation se fait automatiquement.
- Sinon elle doit être explicite.
## Car pratique: la liste chaînée
- Rust doit connaître la taille d'un type **à la compilation**.
- Ici nous avons à faire à un type **récursif**: sa taille est potentiellement infinie.
<pre><code data-trim="hljs rust" class="lang-rust">
enum List {
Elem(i32, List),
Nil,
}
use List::{Elem, Nil};
fn main()
{
let list = Elem(1, Elem(2, Elem(3, Nil)));
}
</code></pre>
## Car pratique: la liste chaînée
- Avec un `Box<T>`{.rust} sa taille est connue.
<pre><code data-trim="hljs rust" class="lang-rust">
#[derive(Debug)]
enum List {
Elem(i32, Box&lt;List&gt;),
Nil,
}
use List::{Elem, Nil};
fn main()
{
let list = Elem(1, Box::new(Elem(2, Box::new(Elem(3, Box::new(Nil))))));
println!("{:?}", list);
}
</code></pre>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment