배열이나 클래스 등 참조형식의 자료 구조들은 대충 등호로 값을 넣어주면 이게 겉으로는 잘 돌아가는 것 처럼 보이지만 사실 안에서 지들끼리 실시간 배끼기를 한다.
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[5];
b = a;
b[0] = 10;
foreach(int n in a)
{
Console.Write($"{n}, ");
}
Console.Write('\n');
foreach(int n in b)
{
Console.Write($"{n}, ");
}
// 결과
// 10, 2, 3, 4, 5
// 10, 2, 3, 4, 5
b = a를 해줬을 때 a의 값을 끌어오는 것이 아닌 a의 값이 저장된 메모리 상의 물리적 주소를 b에 담아오기 때문이다. a의 값을 바꾸든 b의 값을 바꾸든 이 경우 둘이 서로의 값을 배껴가서 개별적인 값 관리가 이루어지지 않는다.
이렇게 얕은 복사가 일어나면 bfs처럼 원본 데이터를 보존해야하는 문제에서 가장 마지막 결과만을 추적해나가는 bfs도 아니고 dfs도 아닌 마치 숙제하기 싫은 애가 한장 풀고 책 덮어버리는 느낌의 코드가 탄생한다. 하지만 얕은 복사가 필요한 경우도 많다. 하나의 값이 여러 이름으로 관리되어야하는데 동시적으로 값이 변해야한다면 참조를 끌어오는 얕은 복사가 같은 일 여러 번 반복하지 않도록 도와준다.
얕은 복사는 그냥 저렇게 대충 등호로 때워주면 끝이고 깊은 복사는 값을 하나하나 붙여주면 된다.
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[5];
for(int i = 0; i < 5; i++)
{
b[i] = a[i];
}
b[0] = 10;
foreach(int n in a)
{
Console.Write($"{n} ");
}
Console.Write('\n');
foreach(int n in b)
{
Console.Write($"{n} ");
}
// 결과
// 1 2 3 4 5
// 10 2 3 4 5
클래스는 클래스 안에서 새로운 값을 선언하고 복사한 다음 return해주면 된다.