RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR
'참조형식'에 해당되는 글 1
(훈스닷넷에서 답변했던 내용인데 의외로 헷갈려하는분도 있을것 같아서 포스팅으로 옮깁니다.)


ref 키워드는 메서드의 인자로 사용할 수 있는데, 이를 사용하면 값형식이든, 참조형식이든 인자로 넘긴값을 메서드에서 사용 후, 변경된 값을 다시 그대로 받을 수 있습니다.
ref 키워드 없이 호출을 하게되면, 메서드에 복사본이 넘어가게되어 메서드 내에서 변경되더라도 메서드가 끝난 이후에는 원래값(넘길때 주었던)이 그대로 남아 있게 됩니다.

여기서 참조형식을 넘겨줄때 의문이 생기는데요, 참조형식은 원래 부터가 참조하는 포인터를 넘겨주기때문에 어짜피 메서드에서 값을 바꾸고 메서드 종료가 되더라도 변경된 값이 유지되는데, ref 키워드를 쓴다한들 참조형식에서는 무슨의미가 있냐? 라는 의문이 생깁니다.

위의 설명에서도 잠깐 나왔지만, 참조형식이 메서드의 매개변수로 넘어과정을 보자면

public class SampleClass { /* 클래스 내용 */ }
public static void Main()
{
    SampleClass sampleClass = new SampleClass();
    WorkWithSampleClass(sampleClass);
}
public static void WorkWithSampleClass(SampleClass obj)
{
}


이와 같은 코드가 있다고 할때, SampleClass sampleClass = new SampleClass(); 처럼 객체 생성이 되면, 아래 그림처럼 실제 객체의 내용은 힙에 생성되고, 그 힙을 가리키는 포인터가 스택에 생성됩니다.
사용자 삽입 이미지
그리고 WorkWithSampleClass(sampleClass); 를 통해 메서드가 호출될때는 아래 그림과 같이 스택에 있는 참조가 복사되어 메서드의 매개변수로 넘어갑니다.
사용자 삽입 이미지
당연히 복사되었으므로 포인터가 가리키는 힙의 객체는 같습니다. 따라서 메서드가 끝난다하더라도, 스택의 복사본만 파괴될뿐, 힙내의 객체는 여전하므로, 힙의 객체 원본을 수정한것은 메서드 호출이 끝나더라도 남아있게 되는것이죠.

그러나,
public class SampleClass { /* 클래스 내용 */ }
public static void Main()
{
   SampleClass sampleClass = new SampleClass();
   WorkWithSampleClass(sampleClass);
}
public static void WorkWithSampleClass(SampleClass obj)
{
    obj = new SampleClass();
}

위의 코드처럼 호출된 메서드 내에서 파라메터로 넘어온 obj 에 직접 다른 객체를 대입하면 어떻게 될까요?
아래 그림과 같은 변화가 메모리상에서 일어납니다.

사용자 삽입 이미지
아까, 메서드 호출시에 복사본이 넘어온다고 했고, 여기에 새로운 객체를 생성해서 대입했으니, 당연한 결과겠죠?

자, 이렇게 됬을때, 메서드가 종료되면? 네, 스택에 있는 복사본은 해당 스코프가 끝났기 때문에 소멸되고, 힙에 있던 객체역시 참조하는 곳이 없게 되므로, 가비지 수집의 대상이 됩니다. 한마디로 둘다 없어지는 거죠.

그렇기 때문에, 메서드가 끝나면, 원래있던 객체를 다시 참조하게 되는것입니다.



자, 이제 ref 키워드를 통해 넘기면..?
사용자 삽입 이미지
맨처음 나왔던, 그림과 동일합니다. 메서드의 매개변수로 스택에 있는 참조를 그대로 넘겨줍니다. 메서드 내에서도 이와 같은 메모리 구조를 유지하고 있기 때문에, 아까 나왔던 매개변수로 전달된 참조에 직접 다른 객체를 대입하게 되면 아래 처럼 됩니다.
사용자 삽입 이미지
이제 아까(ref 키워드를 사용하지 않았을때)와 다른 형세가 되었네요. 기존의 객체는 참조하는곳이 없어져서 가비지 수집의 대상이 되고, 새로 생성한 객체가 스택에 있는 참조의 참조대상이 됩니다.
당연히 메서드 종료 후에도 참조는 새로는 생성한 객체를 가지키게 되겠죠.

간단한 내용이지만, 설명이 굉장히 길어졌는데요. 요약하자면..

ref 키워드로 참조형식을 넘겨주면 참조형식에 직접 대입하여 다른 객체로 바꿀 수 있다.

(아래는 훈스닷넷에 답글을 달면서 만든 샘플 소스입니다.)
2009/03/05 11:10 2009/03/05 11:10
http://lemonwidz.com/tc/trackback/14
HOONS  | 2009/03/05 13:10
좋은글 잘 보았습니다(^^)
레몬  | 2009/03/05 19:29
어익후.. 제 블로그 첫번째 리플의 주인공이시네요^^;;
감사합니다~
anydeveloper  | 2011/02/23 22:57
다소 혼동스러운 개념이었는데, 정말 명확하게 잘 정리해 주셨네요. 좋은 내용 공유해 주신 것에 대해 진심으로 감사드립니다.^^
전체 (23)
사진이야기 (4)
프로그래밍 (18)
  1. Nyaonge's Home  2011
    [C#] ?? 연산자(물음표 두개)
  1. 2012/03 (1)
  2. 2011/12 (2)
  3. 2009/07 (1)
  4. 2009/04 (1)
  5. 2009/03 (9)