object 데이터 타입의 박싱과 언박싱, 클래스(참조 형식), ref키워드, struct의 깊은복사 등 앞으로 나올 여러 C#문법들이
값과 참조, 스택과 힙의 차이에 기반해 설명되기 때문에 이 차이를 확실히 알아야 할 필요가 있습니다.
데이터 형식은 값 형식과 참조형식으로 분류 할 수 있습니다.
stack 과 heap은 C#으로 작성한 프로그램이 사용하는 두가지 메모리 영역입니다.
결론을 간단히 설명하자면 ,
• 값 형식의 변수는 값 데이터를 직접적으로 스택(stack) 메모리에 저장합니다.
• 참조 형식의 변수는 힙과 스택을 함께 이용하는데, 힙 영역에는 데이터를 저장하고 스택 영역에는 데이터가 저장된 힙 메모리의 주소를 저장합니다.
즉 값 형식과 참조 형식은 데이터를 스택에 넣느냐, 힙에 넣느냐가 다릅니다
스택(stack)과 힙(heap)
스택(stack)
- 정적으로 메모리에 할당
- { } 중괄호(코드블럭) 가 끝나면 제거된다 : 장점이자 단점
힙(heap)
- 동적으로 메모리에 할당
- 저장된 데이터를 스스로 제거하는 메커니즘을 갖고 있지 않음 그 대신 , 가비지 컬렉터가 힙에 더 이상 사용하지 않는 객체가 있으면 그 객체를 쓰레기로 간주하고 수거하는 기능을 해줌
값 형식과 스택
스택의 구조는 책상 위에 쌓인 책이라고 생각 할 수 있습니다
맨 밑의 있는 책을 읽고 싶다면 위에 쌓인 책들을 차례대로 걷어내야 가능합니다
{ //코드 블록 시작
int a = 10;
int b = 20;
int c = 30;
} //코드 블록 끝
이렇게 선언된 세 변수 a,b,c는 차례대로 스택에 쌓였다가 코드 블록이 끝나는 }를 만나는 시점에
c, b, a의 순서로 걷혀 제거됩니다
값 형식의 변수는 모두 이 스택에 저장됩니다.
즉, 코드블록이 끝나는 시점에 값 형식의 변수는 제거됩니다.
참조 형식과 힙
반면에 힙은 저장된 데이터를 스스로 제거하는 메커니즘을 갖고 있지 않습니다. 그 대신 , 가비지 컬렉터가 힙에 더 이상 사용하지 않는 객체가 있으면 그 객체를 쓰레기로 간주하고 수거하는 기능을 해줍니다
Q . 그럼 스택 메모리 영역이 있는데 왜 굳이 가비지 컬렉터가 필요한 힙 영역을 사용하는 걸까?
A. 스택에 쌓인 데이터들은 코드블럭이 끝나는 시점에 함께 제거됩니다. (장점이자 단점인 이유)
코드블럭이 끝나는 시점과 상관없이 데이터를 유지하고 싶을 때는 스택의 구조가 발목을 잡는 요소가 되기
때문입니다.
그래서 언제까지라도 프로그래머가 원한다면 데이터를 살릴 수 있는 heap영역을 CLR이 제공하는
것입니다.
힙에 데이터를 올려놓으면 코드 블록이 종료되는 시점과 상관없이 그 데이터는 계속 생명을 유지합니다.
그리고 이 데이터는 프로그래머가 더 이상 사용하지 않는 쓰레기가 됐을 때 가비지 컬렉터가 가져다 버립니다
(이때 메모리에서 삭제)
참조 형식의 변수는 힙과 스택을 함께 이용하는데, 힙 영역에는 데이터를 저장하고 스택 영역에는 데이터가 저장된 힙 메모리의 주소를 저장합니다.
데이터를 저장하는 대신 실제 데이터가 저장된 메모리의 주소를 "참조"한다고 해서 참조 형식인 것입니다.
스택은 블록이 끝난 시점에서 사라졌지만 힙은 여전히 남아 있습니다
헷갈림 주의 : 참조로 반환한다, 참조로 다룬다, 참조를 전달한다
= 데이터가 저장된 힙 메모리의 주소를 반환한다, 주소를 다룬다, 주소를 전달한다로 바꿔생각