c# 에서는 데이터를 메모리에 어떤 방식으로 저장하느냐에 따라 크게 두개의 타입으로 나뉘게 됩니다.
바로 오늘의 주제인 값형식(value types)과 참조형식(reference types)입니다.
c#의 많은 문법들이 사실 이 두 녀석의 특징과 차이로 인해 설명이 되기 때문에 이번 포스팅은 특히 잘 이해 하실 필요가 있습니다.
결론부터 간단히 설명드리자면,
값 형식(value types)은 해당 데이터를 직접적으로 스택(stack) 메모리에 저장하는 반면,
참조 형식(reference types)의 경우 힙(heap) 메모리에 데이터를 저장합니다. 스택(stack) 메모리에는 힙 메모리의 주소를 저장합니다.
무슨 말인지 조금 애매하시죠?
사실 이런 추상적인 설명보단 직접적으로 어떻게 다른지는 코드를 통해 느껴보시는게 빠릅니다.
값 형식(value types) 예시
값 형식의 대표적인 자료형(data types)인 int를 사용한 예제 입니다.
1. 6이라는 데이터 값을 Num 변수에 할당 하였습니다.
2. Num변수를 Num2에 할당 했습니다.
그럼 Num2의 값은 무엇일까요?
output :
당연히 6입니다.
3. 여기서 Num2의 값을 100으로 재 할당을 했습니다.
그러면 최종 Num과, Num2의 값이 무엇일것 같나요?
output :
Num2만 바꿨으니까 Num2값만 바뀌었네요.
여기까지는 너무 직관적이고 당연하게 보입니다.
참조 형식(reference types) 예시
그런데 문제는 참조 형식의 대표적인 자료형(data type)인 array의 예시를 보시면 뭔가 다름을 느끼게 되십니다.
위와 똑같은 식의 코드를 타입만 변경하여 작성해보았습니다.
output :
결과를 확인해보니 아이러니하게도 두 변수의 결과값이 같습니다.
왜 array2의 값만 바꿨는데 array까지 바뀐것일까요?
이제서야 앞서 말씀드렸던 추상적인 이야기를 자세히 풀어야 할때가 된 것 같습니다.
값 형식과 참조 형식의 데이터 저장 방식(with 그림)
1) 값형식의 저장 방법
위 코드를 그림으로 저장 방식을 표현 해보겠습니다.
(1) 먼저 6이라는 데이터가 Num에 할당되는 모습인데요.
보시는것처럼 6이라는 데이터가 자체가 0x004312라는 메모리 주소에 저장이 되고, Num이라는 변수가 해당 데이터를 가리키게 되는 것을 알 수 있습니다. 이때 저장되는 공간은 스택(stack) 메모리입니다.
(2) Num 변수를 Num2변수에 할당하는 코드인데요.
새로운 메모리 주소(0x004552)에 데이터값(여기선 6)을 그대로 복사하고, Num2라는 변수명이 해당 메모리 공간을 가리키게 됩니다.
(3) Num2의 변수에 100으로 값을 재할당합니다.
이때 앞서 새로 생긴 메모리공간(0x004552)에 값이 100으로 변경되는것입니다.
그래서 최종적으로 Num의 값은 6이고 Num2의 값은 100이 됩니다.
2) 참조 형식의 저장 방법
다음은 참조형식 예시에서 다루었던 아래 코드를 그림으로 풀어보겠습니다.
(1) array로 생성한 데이터가 힙(heap)이라는 메모리 공간(0x053112)에 생성이 됩니다.
그리고 그 메모리 공간의 주소명(0x053112)은 스택 메모리 공간(0x004312)에 저장이 됩니다.
(2) array2 변수에 array를 할당합니다.
이때 힙에 저장된 데이터인{1,2}와 같은 값임으로 힙에서는 따로 생성을 하지 않습니다.
하지만 스택에서 새로운 메모리(0x004325)공간을 생성하고, 기존에 힙에 생성되었던 메모리 주소를 다시 가리킵니다.
(3) array2의 첫번째 요소를 3으로 변경 시킵니다.
실제 힙 메모리에 저장되어있던 데이터 값이 변경이 됩니다.
이제 조금 감이 오시나요?
스택(stack)에서는 서로 다른 메모리를 공간을 생성했지만, 그 안에 있는 내용물(메모리주소)이 같기 때문에
결과적으로 두개의 변수(array, array2)는 서로 같이 움직이게 되는 것입니다.
어떤 데이터가 값형식? or 참조 형식?
1) 값형식(value types)에는 아래와 같이 많은 데이터타입이 해당됩니다.
2) 참조형식(reference types)에는
String, Arrays, Class, Delegate 가 해당 됩니다.
참고로 String은 참조형식이지만 작동하는 모습은 마치 값 형식같은 모습을 보이는데요.
해당 내용은 해당 포스트를 참조하기 바랍니다.
이 글과 읽으면 좋은글
'c#' 카테고리의 다른 글
[c#] 형변환(type casting) | 명시적 변환 vs 암시적 변환 (0) | 2022.05.18 |
---|---|
[c#] 값 형식 처럼 작동하는 string(참조 형식) (0) | 2022.05.17 |
[c#] Attribute(어트리뷰트) 란? (0) | 2022.05.16 |
[c#] enum(열거형) 사용 이유/사용법 (3) | 2022.05.16 |
[c#] 델리게이트(대리자) 익명 함수로 선언 (0) | 2022.05.13 |
댓글