Rust Guide > Documentation > Collections > Cell

Introduction

The Cell class in Rust provides interior mutability, a design pattern that allows you to mutate data even when there are immutable references to that data. Unlike RefCell, Cell does not enforce Rust's borrowing rules at runtime and is intended for simpler data types that can be copied.

Using Cell

The Cell class can be used to create a mutable data structure that can be safely accessed and modified. Here is a basic example:

use std::cell::Cell;

fn main() {
    let data = Cell::new(5);
    data.set(10);
    println!("Value: {}", data.get());
}
// Output: Value: 10

Key Methods

Below are some of the key methods exposed by the Cell class:

new

Creates a new Cell containing the given value.

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    println!("Created Cell with value: {}", cell.get());
}
// Output: Created Cell with value: 5

get

Gets the current value of the Cell.

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    let value = cell.get();
    println!("Value: {}", value);
}
// Output: Value: 5

set

Sets the value of the Cell.

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    cell.set(10);
    println!("Updated value: {}", cell.get());
}
// Output: Updated value: 10

swap

Swaps the values of two Cell instances.

use std::cell::Cell;

fn main() {
    let cell1 = Cell::new(5);
    let cell2 = Cell::new(10);
    cell1.swap(&cell2);
    println!("Cell1: {}, Cell2: {}", cell1.get(), cell2.get());
}
// Output: Cell1: 10, Cell2: 5

replace

Replaces the value of the Cell with a new value, returning the old value.

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    let old_value = cell.replace(10);
    println!("Old value: {}, New value: {}", old_value, cell.get());
}
// Output: Old value: 5, New value: 10

Example Usage

Example 1: Basic Usage

use std::cell::Cell;

fn main() {
    let data = Cell::new(5);
    data.set(10);
    println!("Value: {}", data.get());
}
// Output: Value: 10

Example 2: Get and Set

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    cell.set(10);
    println!("Updated value: {}", cell.get());
}
// Output: Updated value: 10

Example 3: Swapping Values

use std::cell::Cell;

fn main() {
    let cell1 = Cell::new(5);
    let cell2 = Cell::new(10);
    cell1.swap(&cell2);
    println!("Cell1: {}, Cell2: {}", cell1.get(), cell2.get());
}
// Output: Cell1: 10, Cell2: 5

Example 4: Replacing Value

use std::cell::Cell;

fn main() {
    let cell = Cell::new(5);
    let old_value = cell.replace(10);
    println!("Old value: {}, New value: {}", old_value, cell.get());
}
// Output: Old value: 5, New value: 10

Example 5: Cell with Copy Types

use std::cell::Cell;

fn main() {
    let cell = Cell::new((1, 2, 3));
    let value = cell.get();
    println!("Value: {:?}", value);
    cell.set((4, 5, 6));
    println!("Updated value: {:?}", cell.get());
}
// Output:
// Value: (1, 2, 3)
// Updated value: (4, 5, 6)

Considerations

  • Cell only works with types that implement the Copy trait. For non-Copy types, use RefCell instead.
  • Cell is not thread-safe. For thread-safe interior mutability, use Mutex or RwLock.
  • Because Cell allows for interior mutability, it can be used to break Rust's borrowing rules, so use it carefully.

See Also

  • RefCell - Provides interior mutability with runtime borrowing checks for non-Copy types.
  • Mutex - A mutual exclusion primitive useful for protecting shared data across threads.
  • RwLock - A reader-writer lock for allowing concurrent reads or exclusive writes across threads.
  • Arc - An atomic reference-counted smart pointer for shared ownership across threads.