Boxing & Unboxing

최정훈·2024년 9월 29일
int i = 123;    //값 타입
object o = i;  // 박싱, 암묵적인 형변환이 가능
int j = (int)o;// 언박싱, 명시적인 형변환을 통해서 가능
  • Boxing 값 타입을 참조 타입으로 변환하는 작업. Heap영역에 저장한다. Heap영역에 공간을 할당해서 Stack에 있는 값을 복사한다. 그리고, Stack 메모리에는 값이 저장되어있는 객체를 가리키는 heap 메모리의 주소를 저장한다.

  • Unboxing 참조 타입의 값을 값 타입으로 변환하는 작업. Stack영역에 저장한다. 명시적인 형변환을 통해서 이루어진다.


  • Boxing과 Unboxing이 성능에 미치는 영향 단순히 변수에 값을 할당하는 것과 비교했을 때, 이 둘은 더 비용이 많이 드는 과정이다. 값 타입을 boxing할 때, 새로운 오브젝트가 할당되고 생성되어야 한다. unboxing 또한 마찬가지이다. 하지만, unboxing에는 추가적인 이슈가 있는데, 가비지를 생성한다는 것이다. 즉, 자체적인 오버해드에 더불어서 GC를 동작하는 잠재적인 오버해드가 추가적으로 있는 셈이다. ⇒ 결론적으로 boxing, unboxing을 사용하는 것은 지양된다.


  • Generic의 등장 generic(제네릭)의 등장으로 인해서 박싱과 언박싱의 사용을 줄일 수 있게 되었다. 기본 컬렉션 중 하나인 ArrayList와 List를 비교해보자.
    ArrayList a = new ArrayList();
    a.Add(1);
    a.Add("2");
    a.Add(3.5f);
    ArrayList는 내부적으로 object 배열을 가지고 있다. 그렇기 때문에, 타입과 상관없이 값을 보관할 수 있다는 장점이 있다. 하지만, 이는 값 형식의 데이터에 한해서 반드시 박싱을 일으키게 한다.(object의 배열임으로) ArrayList는 값 자체를 저장하는 것이 아닌, object 타입으로 박싱되어 메모리 어딘가에 할당되어 있는 값의 ‘주소값’을 저장하고 있다. 만약 이를 boxing없이 사용하고 싶다면 각각의 타입에 따라서 따로 정의해야 할 것이다. 하지만, 이는 중복되는 코드를 늘리는 비효율적인 프로그래밍이다. generic의 추가로 한번의 정의로 boxing문제와 코드 중복 문제를 해결할 수 있게 되었다. List는 내부적으로 T타입의 배열을 가지고 있다.
    List<int> list = new List<int>();
    list.Add(1);
    list.Add(2);
    list.Add(3);
    이는 해당 값을 그대로 복사해오기 때문에, boxing이 일어나지 않는다.


  • 배열 자료구조
    1. Array

      • 고정된 크기의 요소들을 저장할 수 있는 컬렉션

      -배열의 길이는 생성시간에 결정, 변경 불가

      -인덱스를 사용하여 요소에 직접 접근 가능

      -다차원 배열 지원

    2. List

      -동적으로 크기가 조정될 수 있는 컬렉션

      -요소의 추가, 삭제, 수정 등이 자유로움

      -인덱스를 사용하여 요소에 직접 접근 가능

      -Generic으로 구현되어 타입 안정성 보장

    3. ArrayList

        -동적으로 크기가 조정될 수 있는 컬렉션
        
        -요소의 추가, 삭제, 수정 등이 자유로움
        
        -인덱스를 사용하여 요소에 직접 접근 가능
        
        -boxing, unboxing으로 인한 성능저하가 있을 수 있음

  • Generic 자료구조
컨테이너자료구조
List<>배열
SortedSet<>레드-블랙 트리
HashSet<>해시 테이블
Dictionary<,>해시 테이블
SortedList<,>배열
SortedDictionary<,>레드-블랙 트리
profile
게임개발자(희망)의 공부일지

0개의 댓글