얕은 복사, 깊은복사

CJB_ny·2022년 7월 24일

C#

목록 보기
11/24
post-thumbnail
namespace TestCSharp
{
    class MyClass
    {
        public int fieldValue1;
        public int fieldValue2;
    }

    public class Program
    {
        static void Main(string[] args)
        {
            MyClass source = new MyClass();
            source.fieldValue1 = 10;
            source.fieldValue2 = 20;

            MyClass target = source;
            target.fieldValue2 = 30;

            Console.WriteLine($"{source.fieldValue1}, {source.fieldValue2}");
            Console.WriteLine($"{target.fieldValue1}, {target.fieldValue2}");

        }
    }
}

값은 어떻게 나올까??

1.번

10, 20
10, 30

  1. 번

10, 30
10, 30

답은 2번이다.

얕은 복사

일단 source라는 객체의 메모리를 보자면은

스택힙
다른 데이터다른 데이터
다른 데이터다른 데이터
sourcefieldValue1, fieldValue2
target(source가 가르키는 곳을 똑같이 가르킨다)
다른 데이터다른 데이터

지금 이런식이다.

우리는 지금

MyClass target = source;

이렇게 해주었을 때

target만의 새로운 힙 메모리에 공간을 할당하여 값만 source 로부터 복사해서

target이 새로운 힙메모리의 주소를 가르크게 하고싶다면,

깊은 복사

를 해야한다.

그런데 c#에서는 이런 "깊은 복사"를 자동으로 해주는 구문이 없다.

그래서 자체적으로 깊은 복사를 하는 코드를 구현해야한다.

class MyClass
    {
        public int fieldValue1;
        public int fieldValue2;

        public MyClass DeepCopy()
        {
            MyClass newCopy = new MyClass();
            newCopy.fieldValue1 = this.fieldValue1;
            newCopy.fieldValue2 = this.fieldValue2;  
            return newCopy;
        }
    }

이런식으로 MyClass를 return 하는 생성자를 반환하는 함수를 만들어 주어야한다.

깊은 복사 함수 사용 예제

static void Main(string[] args)
{
	MyClass source = new MyClass();
    source.fieldValue1 = 10;
    source.fieldValue2 = 20;

	MyClass target = source.DeepCopy();
    target.fieldValue2 = 30;

	Console.WriteLine($"{source.fieldValue1}, {source.fieldValue2}");
    Console.WriteLine($"{target.fieldValue1}, {target.fieldValue2}");

}

이렇게해주면 이제 서로 다른 힙메모리를 가지는 객체를 만든 것이고

아까 원한

10, 20
10, 30

이라는 값이 출력되는 것을 확인이 가능하다.

ICloneable.Clone() 👍

System 네임스페이스에 ICloneable이라는 인터페이스가 구현되어있다.

"인터페이스란"?

클래스가 구현해야하는 메소드 목록 이다.

이 인터페이스는 "깊은 복사"기능을 가질 클래스가 있을 경우

해당 클래스는 ICloneable 을 상속하는 것이 좋다.

class MyClass : ICloneable
    {
        public int fieldValue1;
        public int fieldValue2;
        public object Clone()
        {
            MyClass newCopy = new MyClass();
            newCopy.fieldValue1 = fieldValue1;
            newCopy.fieldValue2 = fieldValue2;
            return newCopy;
        }
    }

주의할점 ❗❗❗

지금 책에서는 반환 타입이 MyClass인데

그러면 컴파일 에러 뜸

반환 형식이 object형식이어야하는데

object란?


https://truecode.tistory.com/47 object관련 블로그


object형식은 "상속" 덕분에 어떤 데이터든지 다룰수 있는 데이터 형식이다

int, float, char, string, bool 와 같은 값형식들의 "부모"이다.

object는 "박상", "언박싱"을 통해 힙에 데이터를 올리고

객체가 힙메모리의 주소를 가르키는 형식이다.

int a = 123;
object b = (object)a;        // a에 담긴 값을 박싱하여 힙에 저장
int c = (int)b;              // b에 담긴 값은 언박싱하여 스택에 저장

이런식인 것이다.

결론

반환형식이 object라 힙에 올라가기 때문에 또한 어떤 데이터든지 다룰 수 있기 때문에

(클래스도 복합 데이터 형식이라 힙에 올라간다)

Class 라는 데이터 형식도 담을 수 있기 때문에 ㄱㅊ다는 것이다.

(그런데 MyClass 반환은 왜 안될까...??)

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글