# Rust Smart Pointer erklärt: Box, Rc, Arc und RefCell im Jahr 2026 > Rust Smart Pointer Box, Rc, Arc und RefCell erklärt mit kompilierbaren 2026-Beispielen, einer Entscheidungstabelle und häufigen Interviewfragen. - Published: 2026-07-05 - Updated: 2026-07-07 - Author: SharpSkill - Tags: rust, smart-pointers, memory-management, interview, rust-2024-edition - Reading time: 11 min --- Rust Smart Pointer sind die Werkzeuge, die Ownership-Muster ermöglichen, die der Borrow-Checker allein nicht ausdrücken kann: Heap-Allokation, geteilter Besitz und Mutation hinter einer geteilten Referenz. Wo eine einfache Referenz (`&T`) einen Wert nur ausleiht, besitzt ein Smart Pointer seine Daten und legt zusätzliches Verhalten darüber. Dieser Leitfaden schlüsselt die vier Typen auf, denen jeder Rust-Entwickler in der Produktion und in Interviews begegnet: `Box`, `Rc`, `Arc` und `RefCell`, mit kompilierbaren Beispielen für die Rust-2024-Edition. > **Die Zusammenfassung in einer Zeile** > > `Box` eignet sich für Heap-Allokation mit einem einzigen Besitzer, `Rc` für geteilten Besitz auf einem Thread, `Arc` für geteilten Besitz über Threads hinweg und `RefCell`, um einen Wert durch eine geteilte Referenz zu mutieren. Die Paare `Rc>` und `Arc>` decken geteilten veränderlichen Zustand ab. ## Was Smart Pointer in Rust sind Ein Smart Pointer ist ein Struct, das sich wie ein Zeiger verhält, aber zusätzliche Metadaten oder Fähigkeiten mitbringt. Die meisten implementieren das `Deref`-Trait, sodass `*pointer` und Methodenaufrufe funktionieren, als wäre der Zeiger eine einfache Referenz, sowie das `Drop`-Trait, sodass das Aufräumen automatisch geschieht, wenn der Wert seinen Gültigkeitsbereich verlässt. Die Standardbibliothek liefert die vier hier behandelten Typen, und ihr Verständnis hängt von einem soliden Griff auf [Ownership und Borrowing](/blog/rust/ownership-borrowing-rust-complete-guide) ab, das entscheidet, wer jede Allokation wann freigibt. Der entscheidende Unterschied zu einer Referenz ist der Besitz. `&T` besitzt die Daten, auf die es zeigt, niemals, es kann den Wert also nicht überleben. Ein Smart Pointer besitzt die Daten, kontrolliert ihre Lebensdauer und gibt sie deterministisch frei. Das [Kapitel des Rust Book über Smart Pointer](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html) behandelt sie gerade deshalb als eigene Kategorie, weil sie diese Form aus Besitz plus Verhalten teilen. ## `Box`: Heap-Allokation für rekursive und dimensionierte Typen `Box` ist der einfachste Smart Pointer. Er speichert einen Wert auf dem Heap und hält auf dem Stack einen Zeiger darauf, mit einem einzigen Besitzer und ohne Laufzeit-Overhead über die Allokation selbst hinaus. Seine häufigste Aufgabe ist es, rekursiven Typen eine bekannte Größe zu geben: ein Typ, der sich direkt selbst enthält, wäre unendlich groß, doch eine `Box` ist nur ein Zeiger, ihre Größe steht also fest, unabhängig davon, worauf sie zeigt. Das folgende Beispiel definiert einen Binärbaum. Jeder `Node` hält zwei Kinder, und ohne Indirektion kann der Compiler die Größe von `Tree` nicht berechnen. Jedes Kind in eine `Box` zu verpacken, durchbricht die Rekursion auf Typebene. ```rust // tree.rs #[derive(Debug)] enum Tree { Leaf(i32), // Box puts each child on the heap, so Node has a fixed size (two pointers). Node(Box, Box), } fn sum(tree: &Tree) -> i32 { match tree { Tree::Leaf(value) => *value, // base case: return the leaf Tree::Node(left, right) => sum(left) + sum(right), // recurse into both children } } fn main() { // Build (1) + ((2) + (3)) = 6 let tree = Tree::Node( Box::new(Tree::Leaf(1)), Box::new(Tree::Node( Box::new(Tree::Leaf(2)), Box::new(Tree::Leaf(3)), )), ); println!("sum = {}", sum(&tree)); // sum = 6 } ``` `Box` ist auch dann wichtig, wenn das Verschieben eines großen Werts teuer wäre oder wenn ein Trait-Objekt wie `Box` zurückgegeben wird. In jedem Fall gilt dieselbe Regel: ein Besitzer, automatisch freigegeben, wenn die `Box` verworfen wird. ## `Rc`: Geteilter Besitz in Single-Threaded-Code Manchmal braucht ein Wert mehrere Besitzer, von denen keiner offensichtlich der letzte ist, der ihn verwendet. `Rc` (referenzgezählt) löst das, indem es einen Strong-Count darüber führt, wie viele Besitzer existieren. `Rc::clone` erhöht diesen Zähler, ohne die zugrunde liegenden Daten zu kopieren, und jedes Verwerfen verringert ihn. Erreicht der Zähler null, wird der Wert freigegeben. Man betrachte ein Konfigurationsobjekt, das mehrere Worker lesen. Jeder Worker sollte die Konfiguration so lange halten, wie er sie braucht, und die Allokation sollte erst verschwinden, wenn der letzte Worker weg ist. ```rust // shared_config.rs use std::rc::Rc; #[derive(Debug)] struct Config { endpoint: String, timeout_ms: u32, } fn main() { // Rc::new moves Config onto the heap with a strong count of 1. let config = Rc::new(Config { endpoint: "https://api.example.com".to_string(), timeout_ms: 5000, }); // Rc::clone only bumps the reference count; it does not deep-copy Config. let worker_a = Rc::clone(&config); let worker_b = Rc::clone(&config); // All three handles point to the same allocation. println!("endpoint: {}", worker_a.endpoint); println!("timeout: {}", worker_b.timeout_ms); // strong_count reports how many owners currently hold the value. println!("owners: {}", Rc::strong_count(&config)); // owners: 3 } ``` `Rc::clone` explizit aufzurufen (statt `config.clone()`) ist idiomatisch: es signalisiert Lesern, dass die Operation günstig ist und nur einen Zähler berührt. Der Haken ist, dass `Rc` nur geteilte, unveränderliche Referenzen ausgibt. Es kann den geteilten Wert nicht mutieren, und es ist nicht sicher, ihn über Threads zu senden. Die [`Rc`-Dokumentation](https://doc.rust-lang.org/std/rc/struct.Rc.html) legt beide Einschränkungen dar. ## `RefCell` und interior mutability in Rust Rust erzwingt normalerweise, dass ein Wert entweder über viele unveränderliche Referenzen geteilt oder über genau eine veränderliche Referenz mutiert wird, und prüft dies zur Kompilierzeit. `RefCell` bietet interior mutability: Es erlaubt Code, einen Wert durch eine geteilte Referenz zu mutieren, indem es genau diese Prüfung in die Laufzeit verschiebt. `borrow()` liefert einen geteilten Lese-Guard; `borrow_mut()` liefert einen exklusiven Schreib-Guard. Die Regeln sind identisch, aber Verstöße führen zu einem Panic, statt die Kompilierung scheitern zu lassen. Kombiniert mit `Rc` ergibt das das kanonische Single-Threaded-Muster für geteilten veränderlichen Zustand, `Rc>`: mehrere Besitzer, die alle denselben Wert aktualisieren können. ```rust // counter.rs use std::rc::Rc; use std::cell::RefCell; // Rc gives shared ownership; RefCell allows mutation through a shared reference. type SharedCounter = Rc>; fn increment(counter: &SharedCounter) { // borrow_mut() hands out an exclusive reference, checked at runtime. *counter.borrow_mut() += 1; } fn main() { let counter: SharedCounter = Rc::new(RefCell::new(0)); let handle_a = Rc::clone(&counter); let handle_b = Rc::clone(&counter); increment(&handle_a); increment(&handle_b); increment(&counter); // borrow() gives a shared read guard; the value is now 3. println!("count = {}", counter.borrow()); // count = 3 } ``` > **RefCell verschiebt die Borrow-Prüfung in die Laufzeit** > > `borrow_mut()` aufzurufen, während ein anderer `borrow()`- oder `borrow_mut()`-Guard noch aktiv ist, führt zu einem Panic mit `already borrowed: BorrowMutError`. Die Sicherheitsgarantien bleiben bestehen, aber ein Logikfehler, den der Compiler abgefangen hätte, wird zum Absturz zur Laufzeit. Guards sollten kurzlebig sein, und man sollte vermeiden, einen Borrow über einen Funktionsaufruf hinweg zu halten, der dieselbe `RefCell` erneut betreten könnte. Interior mutability ist auch der Ort, an dem sich Referenzzyklen verstecken. Zwei `Rc>`-Werte, die aufeinander zeigen, halten den Strong-Count des jeweils anderen für immer über null, sodass keiner je freigegeben wird. Die Lösung ist `Weak`, ein nicht besitzender Handle, der den Strong-Count nicht beeinflusst; die klassische Durchgehung findet sich in [Learn Rust With Entirely Too Many Linked Lists](https://rust-unofficial.github.io/too-many-lists/). ## `Arc`: Thread-sichere Referenzzählung für Nebenläufigkeit `Arc` (atomar referenzgezählt) ist das Multi-Threaded-Geschwister von `Rc`. Die öffentliche API ist nahezu identisch, aber der Zähler nutzt atomare Operationen, sodass das Klonen und Verwerfen eines `Arc` aus mehreren Threads gleichzeitig korrekt bleibt. Diese Atomarität ist der Grund, warum `Arc` nur gewählt wird, wenn das Teilen eine Thread-Grenze überschreitet: die atomare Erhöhung ist messbar langsamer als die einfache, die `Rc` verwendet. Da `Arc` weiterhin unveränderliche Referenzen ausgibt, braucht Mutation über Threads hinweg ein Synchronisationsprimitiv. `Mutex` ist der übliche Partner und ergibt das Muster `Arc>`, das `Rc>` für nebenläufigen Code spiegelt. Das Beispiel startet vier Threads, die jeweils eine geteilte Summe tausendmal erhöhen. ```rust // parallel_sum.rs use std::sync::{Arc, Mutex}; use std::thread; fn main() { // Arc is safe to share across threads; Mutex serializes access to the inner value. let total = Arc::new(Mutex::new(0u64)); let mut handles = Vec::new(); for _ in 0..4 { // Each thread gets its own Arc handle (an atomic count bump). let total = Arc::clone(&total); handles.push(thread::spawn(move || { for _ in 0..1000 { // lock() blocks until the mutex is free, then returns a guard. let mut value = total.lock().unwrap(); *value += 1; } })); } for handle in handles { handle.join().unwrap(); // wait for every thread before reading } println!("total = {}", *total.lock().unwrap()); // total = 4000 } ``` Der Compiler erzwingt die Grenze von selbst: `Rc` ist nicht `Send`, also scheitert der Versuch, ein solches in `thread::spawn` zu verschieben, an der Kompilierung und drängt in Richtung `Arc`. Nach `Arc` innerhalb eines einzigen Threads zu greifen, bezahlt nur für Atomik, die nie genutzt wird. Die [`Arc`-Dokumentation](https://doc.rust-lang.org/std/sync/struct.Arc.html) behandelt die Garantien zur Speicherordnung im Detail, und `Arc>` trägt einen Großteil des geteilten Zustands in [asynchronem Rust mit Tokio](/blog/rust/rust-async-await-tokio-futures-concurrency). ## Box vs Rc vs Arc vs RefCell: wann man welches verwendet Die vier Typen setzen sich entlang zweier Achsen zusammen: wie viele Besitzer ein Wert hat und ob er durch einen geteilten Handle mutiert werden kann. Die Tabelle fasst die Kompromisse zusammen. | Typ | Besitz | Mutation über geteilten Handle | Thread-sicher | Overhead | |------|-----------|----------------------------|-------------|----------| | `Box` | Einzeln | Nein | Ja, wenn `T: Send` | Nur Heap-Allokation | | `Rc` | Geteilt | Nein | Nein | Nicht-atomarer Zähler | | `Arc` | Geteilt | Nein | Ja | Atomarer Zähler | | `RefCell` | Einzeln | Ja (zur Laufzeit geprüft) | Nein | Laufzeit-Borrow-Flag | Der praktische Entscheidungsbaum ist kurz. Ein Besitzer auf dem Heap nötig: `Box`. Viele Besitzer auf einem Thread nötig: `Rc`. Viele Besitzer über Threads hinweg nötig: `Arc`. Einen geteilten Wert mutieren nötig: den inneren Typ in `RefCell` (Single-Thread) oder `Mutex` (Multi-Thread) verpacken. Die Effective-Rust-Empfehlung zu [Referenz- und Zeigertypen](https://www.lurklurk.org/effective-rust/) kommt zur selben Schichtung. Man beginnt mit der am wenigsten mächtigen Option und fügt Fähigkeiten erst hinzu, wenn der Compiler dazu zwingt. ## Rust Smart Pointer: Interviewfragen Smart Pointer sind ein verlässliches Interviewthema, weil sie prüfen, ob ein Kandidat Ownership versteht statt nur Syntax. Die folgenden Fragen tauchen häufig auf, und weitere sind im [Interview-Modul zu Rust Smart Pointern](/technologies/rust/interview-questions/smart-pointers) gesammelt. **Was ist der Unterschied zwischen `Rc` und `Arc`?** Beide bieten geteilten Besitz über Referenzzählung. `Rc` nutzt einen nicht-atomaren Zähler und ist auf einen einzigen Thread beschränkt; `Arc` nutzt atomare Operationen und kann zu geringen Laufzeitkosten über Threads geteilt werden. Der Compiler erzwingt die Trennung: `Rc` ist weder `Send` noch `Sync`, kann also keine Thread-Grenze überschreiten. **Warum `Rc` mit `RefCell` kombinieren?** `Rc` gewährt geteilten Besitz, aber nur unveränderlichen Zugriff. `RefCell` fügt interior mutability hinzu und lässt Besitzer den Wert durch eine geteilte Referenz mit Laufzeit-Borrow-Prüfungen mutieren. Zusammen ist `Rc>` der idiomatische Single-Threaded-Baustein für geteilten veränderlichen Zustand. **Wie kann Referenzzählung in Rust Speicher lecken?** Zwei `Rc`- (oder `Arc`-)Werte, die aufeinander verweisen, bilden einen Zyklus, dessen Strong-Counts nie null erreichen, sodass die Allokation nie freigegeben wird. Den Zyklus mit `Weak` zu durchbrechen, das eine nicht besitzende Referenz hält, stellt korrektes Aufräumen wieder her. **Wann ist `Box` gegenüber `Rc` vorzuziehen?** Immer dann, wenn ein einziger Besitzer genügt. `Box` hat keinen Overhead durch Referenzzählung und ist damit die Standardwahl für Heap-Allokation, rekursive Typen und Trait-Objekte. Nach `Rc` greift man nur, wenn echter geteilter Besitz erforderlich ist. ## Fazit Rust Smart Pointer verwandeln Ownership von einer Einschränkung in eine Menge zusammensetzbarer Bausteine. Die Wahl zwischen ihnen folgt direkt aus der Form des Problems: - `Box` wählen, wenn ein Wert einen einzigen Heap-Besitzer braucht, ein rekursiver Typ eine feste Größe braucht oder eine Funktion ein Trait-Objekt zurückgibt. - `Rc` für mehrere Besitzer auf einem Thread verwenden und in dem Moment auf `Arc` wechseln, in dem der Besitz eine Thread-Grenze überschreitet. - `RefCell` für interior mutability in Single-Threaded-Code hinzufügen und `Mutex` für das nebenläufige Äquivalent, wobei Borrow- und Lock-Guards kurzlebig bleiben. - Sie bewusst kombinieren: `Rc>` für geteilten veränderlichen Zustand auf einem Thread, `Arc>` über Threads hinweg. - Auf Referenzzyklen zwischen gezählten Zeigern achten und sie mit `Weak` durchbrechen, um Lecks zu vermeiden. - Standardmäßig zum am wenigsten mächtigen Typ greifen und den Compiler sagen lassen, wann mehr Fähigkeit erforderlich ist. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/de/blog/rust/rust-smart-pointers-box-rc-arc-refcell