Struct vs. Class

Struct

  • 값 타입
  • allocation 및 deallocation 시 참조 타입보다 소요가 적다
  • stack에 저장
    • nested struct 구조인 경우 inline
  • member들은 private by default
struct A
{
  public int i;	
}

struct B
{
  public A a;
  public float f;
}

// ...

B b = new B();
b.a.i = 10;  // b.a = new A(); 할 필요 없음
Console.WriteLine(b.a.i);  // 정상적으로 10 출력

struct의 제약

  • 일반적으로, 함수 인자로 전달되거나 함수에서 반환할 때 복사된다
    • 참조 인자 전달은 ref 키워드를 이용해 가능하다
    • 최신 C# 역시 참조 반환을 허용한다
  • 같은 구조체를 가리키는 여러 개의 변수를 선언할 수 없다

Class

  • 참조 타입
  • Heap에 저장
    • garbage-collected 된다
  • 멤버 변수가 많고 클수록 할당하는 데 struct보다 유리하다
  • struct와 동일하게, member들은 private by default
public class Demo
{
  public int x;
}

class Program
{
  static void Main(string[] args)
  {
    // int 멤버를 가진 class 객체를 할당하고
    Demo new_demo = new Demo();

    // 그 값을 초기화
    new_demo.x = 5;

    // = operator로는 할당
    // d1, d2 모두 같은 참조를 가리킴
    Demo d1 = new_demo;
    Demo d2 = new_demo;

    new_demo.x = 10;

    // 아래 두 값 모두 10으로 변경
    Console.WriteLine(d1.x);
    Console.WriteLine(d2.x);
  }
}
  • 두 변수가 하나의 동일한 참조를 할 수 있다
  • C# 에서는 class의 객체를 복사하기 위해서는 Object.MemberwiseClone 메서드를 사용한다
    • = operator로는 복사할 수 없다
  • List, Dictionary 등 자료구조는 class이며, Reference type으로 Heap에 할당된다

각 케이스 별 저장되는 위치

  1. Main 함수에 선언된 int -> stack
  2. Class 안에 선언된 int -> Heap
  3. 함수에 인수로 전달된 int -> Stack
    • Stack에 이 인수의 original data의 참조 값을 복사한다
    • Heap에 이 인수의 original data가 있다
  4. 함수에 지역 변수로 선언된 int -> Stack
    • Boxing된 int라면 -> Heap
  5. Class 안에 선언된 Struct -> Heap
    • Struct 안에 선언된 Class -> Heap
    • 이 경우에는 Class를 참조하는 포인터는 나머지 Struct의 멤버와 함께 할당
    • 실제로 포인터가 가리키는, 즉 참조하는 object는 Heap에 할당
  6. ref struct -> Stack

출처