Programming · intermediate

Value vs reference semantics

With value semantics, copying a value produces independently changeable state at the abstraction level of the type. With reference semantics, copying a reference can create another alias to the same object, so mutations through one alias are observable through the other.

Why it matters

Function calls, assignments, collection updates, concurrency, and API design behave differently when data is copied versus aliased. Correct reasoning must follow the specific language and type rather than slogans such as pass by reference.

Mental model

How to reason about value vs reference semantics

Draw names or fields as boxes. A value copy duplicates the represented state into another box; a reference copy duplicates an arrow, leaving two arrows aimed at one mutable object. Languages frequently mix both models and optimize copies without changing semantics.

Analogy

Value copying is giving someone a photocopy they can mark independently; reference copying is giving them another key to the same whiteboard, where either person's edits are shared.

Examples

See the boundary, not just the happy path

Worked example · Reference alias observes mutation

items = ['a']
alias = items
alias.append('b')
# items is now ['a', 'b']

In Python, both names are bound to the same list object. append mutates that shared object rather than rebinding alias.

Worked example · Copy breaks list aliasing

items = ['a']
copy = items.copy()
copy.append('b')

The shallow copy creates a distinct outer list, so appending does not change items. Nested mutable elements would still be shared unless copied more deeply.

Useful contrast · Rebinding is not object mutation

alias = ['new']

This changes which object alias refers to; it does not alter the old list still referenced by items. Assignment and mutation have distinct effects.

Common mistakes

Misconceptions to remove early

Labelling an entire language pass-by-reference

Parameter passing rules are language-specific. For example, Python passes object references by value: a callee can mutate a passed mutable object but rebinding its parameter does not rebind the caller's name.

Assuming a shallow copy removes all sharing

A shallow copy duplicates the outer container but retains references to its elements. Nested mutable objects can therefore remain aliased.

Quick check

Can you predict the result?

1. Two variables refer to the same mutable list. What makes a change visible through both?
  • Mutating the shared list object through either reference.
  • Rebinding one variable to a new list.
  • Printing one variable without modifying it.
Answer: Mutating the shared list object through either reference.
2. Why can a shallow copy still share mutable state?
Answer: It copies the outer container but can retain references to the same nested objects.

Keep building

Authoritative references

Make the idea retrievable.

Study this concept with spaced repetition, next to the commands where you use it.

Get Terminaster