Skip to content
Skilled.dev

Free lesson walkthrough · Rust

Pointers in Rust

Trace shared mutation and reference rebinding in Rust. Follow two aliases through one object update and a new allocation, with explicit ownership notes.

4 min read · Worked code, edge cases, and complexity

The recording uses object references to explain how several variables can reach the same object. In JavaScript, this does not involve exposing a raw memory address or performing pointer arithmetic. It describes the identity relationship that matters when you connect nodes, pass an object to a function, or mutate a shared record.

Draw objects separately from variable names

Suppose child holds an object, and a parent object's child property is assigned that same reference. There is still one child object. Mutating a field through either reference changes the object seen through the other. Creating a second object with equal fields would instead produce a distinct identity.

Assignment changes which value a variable or property holds. Reassigning the local variable child to a different object does not rewrite the parent's property. Deleting the parent's property removes that route to the original object, but another variable may still reach it. Trace arrows after each operation rather than assuming that a change to one name changes every reference.

Follow the value passed into a function

JavaScript passes values as arguments. When a value is an object reference, the function receives that reference value and can use it to mutate the shared object. Reassigning the parameter itself changes only the local binding. This distinction explains why a function may successfully change a node's data but still need to return a new head after replacing the first node.

A shallow copy also preserves references to nested objects. Changing a top-level field on the copy is separate from changing a field inside one of those shared nested objects. The deep-clone guide shows why copying an object graph requires an explicit contract for cycles, aliases, descriptors, and supported types.

Relate references to ownership and lifetime

A garbage-collected runtime can reclaim objects that are no longer reachable under its memory model; removing one reference does not establish that all references are gone or that collection happens immediately. Other languages use ownership, reference counting, or explicit allocation APIs. Keep those mechanisms separate when translating an explanation between languages.

Practice by drawing a three-node chain, saving a reference to its middle node, and then changing the head. Identify which nodes each remaining name can reach. Continue with Linked Lists, where those identity relationships determine whether a mutation preserves or loses the remaining chain.

Distinguish shared mutation from rebinding

The example records four values: [1, 2, 2, 9]. An original object starts with value 1. A second reference initially points to that same object. Mutating through the second reference changes what the original reference sees to 2. Rebinding the second reference to a new object containing 9 leaves the original object at 2.

This trace is about object identity. A copied integer behaves differently because changing the copy does not mutate a shared object. The exact syntax varies by language: a pointer, a class reference, or an Rc-backed shared allocation can all express this particular example.

Draw the references before changing the code

Use one box for the original allocation and two arrows pointing at it. The mutation changes the box. The reassignment moves only one arrow to a second box. Drawing two boxes from the beginning would incorrectly predict that the first mutation is isolated.

The example uses constant-size data and O(1) work. It deliberately avoids pointer arithmetic, unsafe memory, and borrowed references that outlive their owner. In Rust, the shared-mutation version needs an explicit ownership/interior-mutability mechanism; copying a Box or borrowing it mutably is not interchangeable with a freely shared reference. In Swift, choosing a class instead of a struct is part of making the trace work. When reviewing a larger algorithm, ask both who can reach an object and who can mutate it. Those are separate questions.

Rust example and implementation choices

Rc::clone shares an allocation rather than cloning its integer contents. RefCell permits checked interior mutation through the shared owner, and borrow_mut temporarily supplies mutable access. Runtime borrow violations would panic, so each borrow here stays short. Reassigning alias to a new Rc changes only that owner. Rc is single-threaded; this example does not establish a concurrent sharing policy.

Worked example

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

fn alias_trace() -> Vec<i32> {
    let original = Rc::new(RefCell::new(1));
    let mut alias = Rc::clone(&original);
    let mut trace = vec![*original.borrow()];
    *alias.borrow_mut() = 2;
    trace.push(*original.borrow());
    alias = Rc::new(RefCell::new(9));
    trace.push(*original.borrow());
    trace.push(*alias.borrow());
    trace
}

Continue in Rust

Open Pointers for the complete course explanation. The course keeps your saved programming-language choice. Use this standalone page to inspect the Rust example and run it in your own local environment. Follow the original course sequence when you want the surrounding lesson context and related exercises.

The Rust interview preparation guide connects these language choices with further practice and the cross-language operation reference.

Continue with the lesson

Open the original lesson to explore its full explanation and examples. Your saved programming-language choice stays unchanged. This reading page belongs to that lesson and does not create a separate progress record.