Giả sử bạn có 2 đối tượng A và B, khi thực hiện sao chép đối tượng A sang đối tượng B hoặc ngược lại, sẽ xảy ra hai trường hợp sao chép như sau,
Sao chép cạn là trường hợp hai đối tượng A và B có cùng chung một địa chỉ trong vùng nhớ sau khi sao chép, điều này có nghĩa là A và B cùng chia sẻ chung một nội dung (dữ liệu) nằm trong vùng nhớ đó, nếu A chỉnh sửa nội dung thì B cũng bị thay đổi và ngược lại.
Ví dụ mã nguồn (mình sử dụng Python cho dễ biểu diễn nhé, các ngôn ngữ khác mặc dù cú pháp khác một chút nhưng ý tưởng thì tương tự).
A = [1] # Khởi tạo mảng A chứa 1 phần tử A[0] = 1
B = [2] # Khởi tạo mảng A chưa 1 phần tử B[0] = 2
print id(A) # Địa chỉ vùng nhớ của A là 55500744
print id(B) # Địa chỉ vùng nhớ của B là 40985096
A = B // Sao chép B sang A, đang thực hiện sao chép cạn
print id(A) # Địa chỉ vùng nhớ hiện tại của A là 40985096
print id(B) # Địa chỉ vùng nhớ hiện tại của B là 40985096
id(A) == id(B) # True, A và B có cùng chung địa chỉ vùng nhớ
A[0] = 5 # Nếu A chỉnh sửa phần tử trong vùng nhớ
print B[0] # B cũng bị thay đổi = 5.
Sao chép sâu là trường hợp hai đối tượng A và B có địa chỉ vùng nhớ riêng sau khi sao chép, điều này có nghĩa là sau này, A và B không còn liên quan gì với nhau nữa, mọi sự thay đổi của A không ảnh hưởng gì tới B và ngược lại.
Ví dụ mã nguồn,
A = [1] # Khởi tạo mảng A chứa 1 phần tử A[0] = 1
B = [2] # Khởi tạo mảng A chưa 1 phần tử B[0] = 2
print id(A) # Địa chỉ vùng nhớ của A là 52016840
print id(B) # Địa chỉ vùng nhớ của B là 52010056
import copy
A = copy.deepcopy(B) // Sao chép B sang A, đang thực hiện sao chép sâu
print id(A) # Địa chỉ vùng nhớ hiện tại của A là 52007688
print id(B) # Địa chỉ vùng nhớ hiện tại của B là 52010056
id(A) == id(B) # False, A và B không còn chung vùng nhớ nữa
A[0] = 5 # Nếu A chỉnh sửa phần tử trong vùng nhớ
print B[0] # Chẳng liên quan gì tới B, B vẫn giữ nguyên và bằng = 2