What is the difference between shallow copy and deep copy?
Interview preparation resource from Gate Smashers.
A shallow copy creates a new outer object but keeps references to the same nested objects. A deep copy creates a new object graph for the mutable nested objects, so changes made through the copy do not affect the original. The exact behavior depends on the language and copying mechanism; immutable values may safely be shared even in a deep copy.
import copy
orig = [1, [2, 3]]
sh = copy.copy(orig)
dp = copy.deepcopy(orig)
# Replacing a top-level element affects only the shallow copy.
sh[0] = 10
# Mutating a nested list affects orig because it is shared with sh.
sh[1][0] = 20
print('orig after shallow changes:', orig)
print('sh:', sh)
print('dp (unchanged):', dp)
# Mutating a nested list in the deep copy does not affect orig.
dp[1][1] = 99
print('orig after deep change:', orig)
print('dp:', dp)class Node implements Cloneable {
int value;
Node child;
Node(int value, Node child) {
this.value = value;
this.child = child;
}
// Shallow clone: referenced objects are not cloned.
@Override
public Node clone() throws CloneNotSupportedException {
return (Node) super.clone();
}
// Recursive deep copy for an acyclic Node structure.
Node deepCopy() {
return new Node(value, child == null ? null : child.deepCopy());
}
}
Node original = new Node(1, new Node(2, null));
Node shallow = original.clone();
shallow.child.value = 99;
System.out.println(original.child.value); // 99: child is shared
Node deep = original.deepCopy();
deep.child.value = 5;
System.out.println(original.child.value); // 99: original is unchangedShallow copy
A shallow copy duplicates only the outer container or object. Its fields or elements that refer to other objects still refer to the same nested objects as the original.
Therefore, changing a top-level field or element in the shallow copy does not change the original, but mutating a shared nested object is visible through both references.
Deep copy
A deep copy duplicates the outer object and recursively copies relevant nested mutable objects. This gives the copy independent mutable state, so a mutation in the copied structure does not affect the corresponding structure in the original.
Deep-copy implementations commonly preserve relationships within the copied graph. For example, they may need to track already copied objects to handle cyclic references without recursing indefinitely.
Language and implementation considerations
Copy behavior is language- and API-specific. A language may provide separate shallow- and deep-copy utilities, or it may require the programmer to define how referenced objects are copied.
Immutable objects can usually be shared safely because they cannot be modified. Objects representing external resources or runtime-specific state may not have a meaningful general-purpose deep-copy operation.
- Python: copy.copy() performs a shallow copy, while copy.deepcopy() performs a recursive copy and uses memoization to handle repeated references and cycles.
- Java: Object.clone(), when implemented using super.clone(), copies fields and is shallow for referenced objects. A deep copy requires explicit copying of referenced mutable objects.
- C++: Copy constructors and copy-assignment operators define copy behavior. Classes that own resources must implement appropriate copy semantics when independent ownership is required.
Choosing between them
Use a shallow copy when sharing nested data is intentional or when that data is immutable. Use a deep copy when the new structure must be independently mutable.
Deep copying generally requires more time and memory because it traverses and allocates objects throughout the structure.
