C#

[C#] 얕은 복사와 깊은 복사 (Shallow Copy & Deep Copy)

윤창범 2021. 10. 15.

얕은 복사와 깊은 복사

  • C# 의 클래스는 기본적으로 참조 형식
  • 스택 영역에 있는 참조가 힙 영역에 할당된 객체의 메모리를 가리킴 (참조값)
  • 얕은 복사는 객체의 참조만 복사하는 것 (단순 복사)
  • 깊은 복사는 객체를 복사하여 '새로운 객체' 를 만드는 것 (복사본 / 전체 복사)

먼저 알아야 할 내용

할당 (Assign)

  • 일반적으로 생성된 객체를 다른 변수로 참조할 경우를 '할당' 한다고 함

 

< person1 의 값을 바꾸면 person2 의 값도 변경된 것과 같음 >

 


얕은 복사

얕은 복사는 아래의 간단한 코드를 예시로 볼 수 있음

< C# 에서는 일반적으로 포인터를 사용하지 않고 권장하지도 않지만 굳이 사용하겠다면 빌드 속성을 변경하여 unsafe 코드를 사용할 수 있음 >

* 포인터는 참조값이 정말 동일한지 판단하기 위한 목적으로 작성하였으며, 실제 적용 시에는 필요하지 않음

 

< 출력 결과, 참조값이 동일하다 >

 

혹시나 이해가 되지 않는다면, 다른 변수와 클래스를 예시로 한 아래의 그림을 참고

 

< 참조값이 동일 -> 새로 생성하는 것이 아닌 동일한 객체를 가리키고 있다 >

 

위의 내용을 얕은 복사라고 하기도 하지만, .NET 프레임워크에서 제공하는 Object 클래스MemberwiseClone 메서드를 활용한 복사도 존재

 

< 주석 참고 >

 

< 출력 결과, 참조값이 다르다 >

이렇게만 보면 한 객체의 모든 정보를 별도로 복사할 수 있는 것 처럼 보이지만, 사실 객체 안에 있는 필드가 값 형식인 경우에만 해당됨

=> 객체의 멤버 변수가 참조 형식이라면 참조는 복사되지만, 참조되는 개체는 별도로 복사하지 않음 (참조값만)

 

 

이게 무슨 말이냐?

Class A 와 Class B 가 있고, Class A 는 Class B 를 포함하고 있다고 한다면

=> 얕은 복사로는 Class A 안에 있는 Class B 의 변수까지는 복사가 불가능함

 

(얕은 복사의 처음에 나온 예시과 같이 참조 복사만 가능함)

 

 

결국 Class A 를 얕은 복사했다고 해도, 안에 포함된 Class B 에 대해서는 동일한 객체 참조를 가지고 있음 (참조값이 동일)

=> 그래서 필요한 것이 원본을 이용하여 별도로 힙 공간에 객체를 복사하는 깊은 복사


깊은 복사

< 이전과 변경된 코드와 주석만 참고 >

 

< 출력 결과, Item 클래스와 안에 있는 Effect 클래스 변수의 참조값 모두 다르다 >

 

깊은 복사의 경우, 깊은 복사를 위한 Clone 메서드만 가지고 있는 .NET 프레임워크의 ICloneable 인터페이스를 활용하거나 새로운 인스턴스를 만들어서 값을 복사하고 반환하는 방식으로 구현할 수 있음

 

=> 방법은 여러가지가 있지만 호환성을 위한 깊은 복사를 원한다면 ICloneable 인터페이스 사용을 권장하고 있음

 


마무리

 

'C#' 카테고리의 다른 글

[C#] 직렬화 (Serialization)  (0) 2021.11.12
[C#] 구조체 (Struct)  (0) 2021.10.22

댓글