Copy-on-write and implementing it for a custom struct
value semantics with shared backing storage.
CoW shares a buffer until mutation, deep-copying only when the buffer is non-unique; Array, Dictionary, Set, String use it; implement with a class storage box and isKnownUniquelyReferenced.
Why it exists
Value semantics promise that copies are independent, but eagerly deep-copying large data on every assignment would be wasteful. Copy-on-write preserves the independent-copy guarantee while deferring the actual copy until it is truly needed.
The mental model
Multiple value copies can point at the same underlying reference-counted buffer. Reads are free. The moment a writer mutates a buffer that has more than one owner, the type clones the buffer first, so the writer mutates a private copy and other owners are unaffected. If the buffer is uniquely owned, the mutation happens in place with no copy.
Which standard types use it
Array, Dictionary, Set, and String all implement copy-on-write, which is why passing or assigning them is cheap until a mutation diverges the copies.
Implementing it for a custom struct
Put the real data inside a private final class, the storage box, and have the struct hold a reference to it. Expose value-type API on the struct. Before any mutating method touches the storage, call isKnownUniquelyReferenced on the reference; if it returns false the storage is shared, so create a fresh copy of the box and point at it before mutating. This reproduces the standard-library behavior.
When it matters
For large structs or custom collections passed around frequently, CoW avoids repeated deep copies while keeping safe value semantics. It is also why naive benchmarking of struct copies can mislead.
The mistakes people make
Believing every struct gets CoW automatically; only types built around reference-counted storage do. Using a struct as the storage box, which cannot be reference-counted or shared.
A concrete example
A custom Matrix struct wraps a private final class holding a flat element array. Two matrices assigned from each other share one storage box. When one calls a mutating set(row:col:value:), the method first checks isKnownUniquelyReferenced; seeing the box shared, it clones the storage, then writes. The other matrix keeps its original data, exactly matching how Array behaves.
Interview question
What is the essential building block for giving a custom struct true copy-on-write semantics?
- a.Conforming the struct to the Copyable protocol
- b.Storing the data in a reference-counted class and checking isKnownUniquelyReferenced before mutatingCorrect
- c.Marking the struct final so the compiler adds CoW automatically
- d.Wrapping the struct in another struct to defer copies
Why? this is the answer
CoW needs reference-counted storage plus an isKnownUniquelyReferenced check to copy only when shared. Structs cannot be reference-counted, and structs do not get CoW automatically.
Just read this? Test yourself on what you have been reading.
Read the original → amitsen.de
- #swift
- #copy-on-write
- #value-types
- #performance
- #memory
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on swift — each one lists the topics its interview covers.
See open roles