---
title: "Cell\u003cT\u003e e RefCell\u003cT\u003e: Mutabilidade Interior"
url: "https://rustlang.com.br/stdlib/cell-refcell/"
markdown_url: "https://rustlang.com.br/stdlib/cell-refcell.MD"
description: "Guia completo de Cell e RefCell em Rust: mutabilidade interior, borrow, borrow_mut, runtime borrow checking e Rc\u003cRefCell\u003cT\u003e\u003e em português."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Cell<T> e RefCell<T>: Mutabilidade Interior

Guia completo de Cell e RefCell em Rust: mutabilidade interior, borrow, borrow_mut, runtime borrow checking e Rc<RefCell<T>> em português.


## O que faz e quando usar

`Cell<T>` e `RefCell<T>` implementam o padrão de **mutabilidade interior** (interior mutability) em Rust. Normalmente, o sistema de borrowing do Rust é verificado em tempo de compilação: você pode ter múltiplas referências imutáveis (`&T`) **ou** uma única referência mutável (`&mut T`), mas nunca ambas ao mesmo tempo. Cell e RefCell permitem **relaxar essa regra**, movendo a verificação para tempo de execução ou contornando-a com tipos `Copy`.

```
  Verificação normal do Rust:        Mutabilidade interior:

  &T  &T  &T  (OK: múltiplas)        &T que permite mutar o interior!
  &mut T       (OK: uma só)           Cell<T>   → get/set para Copy
  &T + &mut T  (ERRO de compilação)  RefCell<T> → borrow checking em runtime
```

Use `Cell<T>` quando:

- `T` implementa `Copy` (inteiros, bool, etc.).
- Você precisa mutar um valor dentro de uma referência compartilhada `&self`.
- Não precisa de referências ao valor interno — apenas get/set.

Use `RefCell<T>` quando:

- `T` **não** implementa `Copy` (String, Vec, structs complexas).
- Você precisa de **referências** ao valor interno (borrow/borrow_mut).
- Sabe que o padrão de borrowing é correto, mas o compilador não consegue provar.

**Importante:** Cell e RefCell **NÃO** são thread-safe! Para multithreading, use `Mutex<T>` ou `RwLock<T>`.

---

## Tipos e Funções Principais

### Cell<T>

| Item | Descrição |
|---|---|
| `Cell::new(value)` | Cria nova Cell contendo `value` |
| `cell.get()` | Retorna uma **cópia** do valor (requer `T: Copy`) |
| `cell.set(value)` | Substitui o valor (sem precisar de `&mut self`) |
| `cell.replace(value)` | Substitui e retorna o valor anterior |
| `cell.into_inner()` | Consome a Cell e retorna o valor |
| `cell.take()` | Retorna o valor e deixa `Default::default()` |

### RefCell<T>

| Item | Descrição |
|---|---|
| `RefCell::new(value)` | Cria nova RefCell contendo `value` |
| `refcell.borrow()` | Retorna `Ref<T>` (referência imutável com runtime check) |
| `refcell.borrow_mut()` | Retorna `RefMut<T>` (referência mutável com runtime check) |
| `refcell.try_borrow()` | Tenta borrow, retorna `Result<Ref<T>, BorrowError>` |
| `refcell.try_borrow_mut()` | Tenta borrow_mut, retorna `Result<RefMut<T>, BorrowMutError>` |
| `refcell.into_inner()` | Consome a RefCell e retorna o valor |
| `refcell.replace(value)` | Substitui o valor e retorna o anterior |

---

## Exemplos de Código

### Cell — mutando valores Copy

```rust
use std::cell::Cell;

struct Contador {
    valor: Cell<u32>,
    nome: String,
}

impl Contador {
    fn new(nome: &str) -> Self {
        Contador {
            valor: Cell::new(0),
            nome: nome.to_string(),
        }
    }

    // Note: &self, NÃO &mut self!
    fn incrementar(&self) {
        let atual = self.valor.get();
        self.valor.set(atual + 1);
    }

    fn valor(&self) -> u32 {
        self.valor.get()
    }
}

fn main() {
    let contador = Contador::new("visitas");

    // Podemos mutar mesmo com referência imutável
    contador.incrementar();
    contador.incrementar();
    contador.incrementar();

    println!("{}: {}", contador.nome, contador.valor());
    // visitas: 3

    // Múltiplas referências imutáveis funcionam
    let ref1 = &contador;
    let ref2 = &contador;
    ref1.incrementar();
    ref2.incrementar();
    println!("Após referências: {}", contador.valor());
    // Após referências: 5
}
```

### RefCell — mutando valores não-Copy

```rust
use std::cell::RefCell;

fn main() {
    let dados = RefCell::new(vec![1, 2, 3]);

    // Empréstimo imutável (borrow)
    {
        let leitura = dados.borrow();
        println!("Leitura: {:?}", *leitura);
        // Múltiplos borrows imutáveis simultâneos são OK
        let leitura2 = dados.borrow();
        println!("Leitura2: {:?}", *leitura2);
    } // Ambos os Ref são dropados aqui

    // Empréstimo mutável (borrow_mut)
    {
        let mut escrita = dados.borrow_mut();
        escrita.push(4);
        escrita.push(5);
        println!("Após push: {:?}", *escrita);
    } // RefMut dropado aqui

    println!("Final: {:?}", dados.borrow());
}
```

### Panic em runtime: violação de borrow

```rust
use std::cell::RefCell;

fn main() {
    let dados = RefCell::new(vec![1, 2, 3]);

    let leitura = dados.borrow(); // borrow imutável ativo

    // PANIC! Não pode ter borrow_mut enquanto borrow imutável existe
    // let mut escrita = dados.borrow_mut();
    // thread 'main' panicked at 'already borrowed: BorrowMutError'

    // Versão segura com try_borrow_mut
    match dados.try_borrow_mut() {
        Ok(mut escrita) => escrita.push(4),
        Err(e) => println!("Não pode mutar: {}", e),
        // Não pode mutar: already borrowed
    }

    println!("Leitura: {:?}", *leitura);
    drop(leitura); // Agora podemos mutar

    // Agora funciona!
    dados.borrow_mut().push(4);
    println!("Após mutação: {:?}", dados.borrow());
}
```

### Padrão: Rc<RefCell<T>> — dados compartilhados mutáveis

`Rc<RefCell<T>>` é o padrão mais comum para **múltiplos donos de dados mutáveis** em single-thread:

```
  +-------+     +-------+     +-------+
  | Dono A |     | Dono B |     | Dono C |
  +---+---+     +---+---+     +---+---+
      |             |             |
      +------+------+------+------+
             |             |
          Rc::clone     Rc::clone
             |             |
        +----+-------------+----+
        |   Rc<RefCell<Vec>>    |
        |   +----------------+  |
        |   | RefCell<Vec>   |  |
        |   | +------------+ |  |
        |   | | Vec dados  | |  |
        |   | +------------+ |  |
        |   +----------------+  |
        +-----------------------+
```

```rust
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
struct No {
    valor: i32,
    filhos: Vec<Rc<RefCell<No>>>,
}

impl No {
    fn new(valor: i32) -> Rc<RefCell<No>> {
        Rc::new(RefCell::new(No {
            valor,
            filhos: Vec::new(),
        }))
    }

    fn adicionar_filho(pai: &Rc<RefCell<No>>, filho: Rc<RefCell<No>>) {
        pai.borrow_mut().filhos.push(filho);
    }
}

fn main() {
    let raiz = No::new(1);
    let filho_a = No::new(2);
    let filho_b = No::new(3);

    // Múltiplas referências ao mesmo nó
    No::adicionar_filho(&raiz, Rc::clone(&filho_a));
    No::adicionar_filho(&raiz, Rc::clone(&filho_b));

    // Mutar um nó filho através de qualquer referência
    filho_a.borrow_mut().valor = 20;

    // A mudança é visível em todos os lugares
    let raiz_ref = raiz.borrow();
    for filho in &raiz_ref.filhos {
        println!("Filho: {}", filho.borrow().valor);
    }
    // Filho: 20
    // Filho: 3
}
```

### Cell para flags e caches em structs

```rust
use std::cell::Cell;

struct Fibonacci {
    cache_calculado: Cell<bool>,
    ultimo_n: Cell<u32>,
    ultimo_resultado: Cell<u64>,
}

impl Fibonacci {
    fn new() -> Self {
        Fibonacci {
            cache_calculado: Cell::new(false),
            ultimo_n: Cell::new(0),
            ultimo_resultado: Cell::new(0),
        }
    }

    // &self — sem mut!
    fn calcular(&self, n: u32) -> u64 {
        if self.cache_calculado.get() && self.ultimo_n.get() == n {
            return self.ultimo_resultado.get();
        }

        let resultado = Self::fib(n);
        self.ultimo_n.set(n);
        self.ultimo_resultado.set(resultado);
        self.cache_calculado.set(true);
        resultado
    }

    fn fib(n: u32) -> u64 {
        match n {
            0 => 0,
            1 => 1,
            _ => {
                let mut a: u64 = 0;
                let mut b: u64 = 1;
                for _ in 2..=n {
                    let tmp = a + b;
                    a = b;
                    b = tmp;
                }
                b
            }
        }
    }
}

fn main() {
    let fib = Fibonacci::new();

    // Mesmo com &fib imutável, o cache é atualizado internamente
    let ref1 = &fib;
    println!("fib(10) = {}", ref1.calcular(10)); // calcula
    println!("fib(10) = {}", ref1.calcular(10)); // usa cache
    println!("fib(20) = {}", fib.calcular(20));  // calcula novamente
}
```

### RefCell para cache preguiçoso de String

```rust
use std::cell::RefCell;

struct Usuario {
    nome: String,
    sobrenome: String,
    nome_completo_cache: RefCell<Option<String>>,
}

impl Usuario {
    fn new(nome: &str, sobrenome: &str) -> Self {
        Usuario {
            nome: nome.to_string(),
            sobrenome: sobrenome.to_string(),
            nome_completo_cache: RefCell::new(None),
        }
    }

    // &self — sem mut, mas atualiza o cache internamente
    fn nome_completo(&self) -> String {
        let cache = self.nome_completo_cache.borrow();
        if let Some(ref cached) = *cache {
            return cached.clone();
        }
        drop(cache); // liberar borrow imutável antes de borrow_mut

        let completo = format!("{} {}", self.nome, self.sobrenome);
        *self.nome_completo_cache.borrow_mut() = Some(completo.clone());
        completo
    }
}

fn main() {
    let user = Usuario::new("Maria", "Silva");

    println!("{}", user.nome_completo()); // calcula e faz cache
    println!("{}", user.nome_completo()); // usa cache
}
```

---

## Padrões Comuns e Anti-padrões

### Quando usar Cell vs RefCell

```rust
use std::cell::{Cell, RefCell};

fn main() {
    // Cell: para tipos Copy — mais eficiente, sem overhead de contagem
    let flag = Cell::new(false);
    let contador = Cell::new(0u32);
    flag.set(true);
    contador.set(contador.get() + 1);

    // RefCell: para tipos não-Copy — quando precisa de referências
    let texto = RefCell::new(String::from("olá"));
    texto.borrow_mut().push_str(" mundo");
    println!("{}", texto.borrow());

    // ERRADO: usar RefCell para tipos Copy (overhead desnecessário)
    // let valor = RefCell::new(42);

    // CORRETO: usar Cell para tipos Copy
    let valor = Cell::new(42);
    valor.set(valor.get() + 1);
}
```

### Anti-padrão: borrow_mut de longa duração

```rust
use std::cell::RefCell;

fn main() {
    let dados = RefCell::new(vec![1, 2, 3]);

    // ERRADO: manter borrow_mut por muito tempo
    // let mut guard = dados.borrow_mut();
    // // ... muito código ...
    // let leitura = dados.borrow(); // PANIC!

    // CORRETO: escopo curto para borrow_mut
    {
        dados.borrow_mut().push(4);
    }
    // Agora borrow() é seguro
    println!("{:?}", dados.borrow());
}
```

### Anti-padrão: RefCell entre threads

```rust
use std::cell::RefCell;

fn main() {
    let dados = RefCell::new(42);

    // ERRO DE COMPILAÇÃO: RefCell não é Sync
    // std::thread::spawn(move || {
    //     *dados.borrow_mut() += 1;
    // });

    // Para threads, use Mutex<T> em vez de RefCell<T>
    // Para múltiplos donos entre threads, use Arc<Mutex<T>> em vez de Rc<RefCell<T>>
    println!("Valor: {}", dados.borrow());
}
```

---

## Garantias de Thread Safety

- `Cell<T>` e `RefCell<T>` **NÃO** implementam `Sync` — **não** são thread-safe.
- `Cell<T>` é `Send` se `T: Send`.
- `RefCell<T>` é `Send` se `T: Send`.
- Nenhum dos dois pode ser compartilhado entre threads com `&` (porque não são `Sync`).
- Para o equivalente thread-safe: use `Mutex<T>` no lugar de `RefCell<T>` e `AtomicT` no lugar de `Cell<T>`.
- `RefCell` mantém um **contador de borrows em runtime**: panics ocorrem se as regras de borrow forem violadas.
- `Cell` não tem overhead de contagem — é zero-cost para tipos `Copy`.

| Single-thread | Multi-thread |
|---|---|
| `Cell<T>` | `AtomicT` / `Mutex<T>` |
| `RefCell<T>` | `RwLock<T>` / `Mutex<T>` |
| `Rc<RefCell<T>>` | `Arc<Mutex<T>>` / `Arc<RwLock<T>>` |

---

## Veja Também

- [Rc e Arc em Rust](/stdlib/rc-arc/) — ponteiros de contagem de referência
- [Mutex e RwLock em Rust](/stdlib/mutex/) — equivalentes thread-safe
- [Send e Sync](/stdlib/send-sync/) — por que Cell/RefCell não são Sync
- [Tipos Atômicos](/stdlib/atomics/) — equivalentes atômicos de Cell
- [Smart Pointers em Rust](/artigos/smart-pointers/) — Box, Rc, Arc, Cell, RefCell
- Documentação oficial: [`std::cell`](https://doc.rust-lang.org/std/cell/)
