2023. 8. 10. 14:26ㆍC#
배열은 클래스이며, 레퍼런스로 동작하기 때문에 선언만 해서는 안되고 new를 이용해 메모리를 만들어야 한다.
int[] nums = new int[5];
string[] strs = new string[3];
nums, strs는 레퍼런스 변수이다.
배열 선언
int[] nums = new int[5];
nums[0] = 1;
nums[1] = 2;
int[] nums = new int[]{1,2,3,4,5};
int[] nums = new int[5]{1,2,3,4,5};
int[] nums = {1,2,3,4,5};
배열의 실제 데이터는 힙 메모리 영역에 생긴다. nums 레퍼런스 변수는 스택 메모리 영역에 생긴다.
배열 접근
print(nums[0]);
for(int i=0; i<5; i++)
{
print(nums[i]);
}
index를 통해 배열에 접근 가능하며 범위를 벗어나면 오류가 생긴다. 함수 내에서 출력 후 nums 레퍼런스 스택 메모리가 사라지고, 힙 메모리에 있는 실제 데이터는 레퍼런스가 없어졌으므로 가비지 컬렉터가 지우게 된다.
배열 예제 1
int[] nums;
void Start()
{
nums = new int[5]{1,2,3,4,5};
for(int i=0; i<5; i++)
{
print(nums[i]);
}
}
위와 같이 nums 배열이 함수 바깥에서 선언되면 힙 데이터 영역에 생기게 되며 Start 함수가 끝나도 해당 레퍼런스 변수와 배열 데이터는 사용할 수 있다. 나중에 클래스가 사라질 때 둘 다 사라진다.
배열 예제 2
public class Test : MonoBehaviour
{
public int[] nums;
void Start()
{
for(int i =0; i < nums.Length; i++)
{
print(nums[i]);
}
}
}
위의 예제는 유니티에서 배열 값을 입력받는다.

리스트
배열과 비슷하다. Generic 문법이 있어 타이핑이 조금 더 오래 걸린다. 추가 삭제가 가능하다.(Add, Remove, RemoveAt, RemoveAll)
List<int> arr = new List<int>()
List<int> strs = new List<int>(){1,2,3};
public class Test : MonoBehaviour
{
void Start()
{
List<int> nums = new List<int>() {1,2,3};
nums.Add(100);
nums.RemoveAt(0);
for(int i = 0; i < nums.Count; i++)
{
print(nums[i]);
}
}
}
리스트에 100이라는 요소가 추가되고, RemoveAt을 통해 0번 인덱스 요소가 지워진다. 값 1이 지워지면 2가 인덱스 0이 된다. nums 변수 레퍼런스는 스택 메모리 영역, 리스트 내용은 힙 메모리 영역에 저장된다.
리스트 예제
public class Test : MonoBehaviour
{
public List<GameObject> objs;
void Start()
{
objs = new List<GameObject>();
GameObject obj1 = new GameObject();
obj1.name = "아이템1";
objs.Add(obj1);
GameObject obj2 = new GameObject();
obj2.name = "아이템2";
objs.Add(obj2);
Destroy(objs[0]);
objs.RemoveAt(0);
for (int i = 0; i < objs.Count; i++)
{
print(objs[i].name);
}
}
}
obj1, obj2를 생성하고, 레퍼런스로 리스트에 추가하고 Destroy로 인덱스 0에 있는 실제 오브젝트를 삭제하고 objs.removeAt으로 남아있는 리스트에서 삭제한다. 리스트에서도 지웠다면 나중에 추가된 리스트 요소가 다시 인덱스 0이 된다. 모든 데이터는 힙 메모리 영역에 저장된다.
Destroy만 실행되면, Hierarchy 상에서 오브젝트는 지워지지만 리스트에는 Missing으로 아래와 같이 남아있게 된다.

해당 리스트를 지우기 위해서 objs.removeAt을 사용하는 것이다.
(**순서가 반대로 되면 오류가 생긴다.)
'C#' 카테고리의 다른 글
[C#] 필드와 지역 변수의 구별 (0) | 2023.10.25 |
---|---|
[C#] 클래스의 소유와 참조 / 역참조와 상호 참조 / 자기 참조 (0) | 2023.08.10 |
[C#] 클래스(Class) / 구조체와 클래스의 차이 / 스택 메모리와 힙 메모리 / 상속(inheritance) (0) | 2023.08.09 |
[C#] 구조체(Struct)와 생성자, this 키워드 (0) | 2023.08.08 |
[C#] 함수의 오버로딩(Overloading) (0) | 2023.08.07 |