iOS/Common

[Swift] 구조체 vs 클래스(Struct vs Class)

TDCIAN 2021. 7. 13. 19:00

무려 스탠포드 대학교에서 SwiftUI 강의를 무료로 오픈해주셨습니다!(사진에 링크 달아놨어요!)

 

처음 개발 세계에 입문했을 때, 말 그대로 '뭘 모르는지도 모르는' 상태였을 때

가장 자주 부딪혔던 난관 중 하나가 구조체(struct)와 클래스(class)를 비교하는 것이었습니다.

 

물론 지금도 아직 배우고 이해해야 할 내용들이 산더미이지만!

주저하고 있는 주니어를 위해 한 번 공부한 내용 나눠보려 합니다...

 

위 사진은 스탠포드 대학교 강의 중 소개 된 정리 내용이고,

아래는 KxCoding을 통해 공부한 내용입니다!

 

(1) 구조체(값 형식)

- 구조체는 메모리 공간으로 스택을 사용하고, 스택에 값을 저장합니다.

- 값을 전달할 때마다 복사본을 생성합니다.

- 메모리 관리 방식

  - 값 형식에서는 인스턴스가 속한 스코프가 종료되면 메모리에서 자동으로 제거됩니다.

- Structure(Int나 String, Swift Collection 등 포함), Enumeration, Tuple이 해당됩니다.

- 상대적으로 적은 데이터를 필요로 하고 상속이 필요 없다면 값 형식을 생성합니다.

- 함수형 프로그래밍과 프로토콜 지향 프로그래밍에서는 주로 구조체로 구현합니다.

- 동일성 비교 방법

  - 값 형식이 저장되는 메모리 공간은 스택입니다.

  - 하나의 공간에 저장되기 때문에, 값을 비교할 때는 비교연산자만 사용해도 충분합니다.

 

 

(2) 클래스(참조 형식)

- 클래스는 메모리 공간으로 힙을 사용하고, 힙에 값을 저장합니다.

- 스택에는 힙에 저장되어 있는 값의 주소를 저장합니다.

- 값을 전달하면 복사본은 생성하지 않고, 주소만 전달합니다.

- 소멸자(deinitializer)와 상속(Inheritance)은 클래스에서만 지원합니다.

- 메모리 관리 방식

  - 참조 형식에서는 스코프에 관계 없이 레퍼런스 카운팅을 통해 메모리를 관리합니다.

- Class, Closure가 해당됩니다.

- 객체 지향 프로그래밍에서는 대부분 참조 형식인 클래스로 구현합니다.

- 동일성 비교 방법

  - 참조형식은 값을 힙에 저장하고, 메모리 주소를 스택에 저장합니다.

  - 두 개의 공간에 저장되기 때문에, 비교하는 방법도 두 가지가 필요합니다.

  - 값을 비교할 때는 비교 연산자를 사용하고, 메모리 주소를 비교할 때는 항등 연산자를 사용합니다.

  - 클래스에서의 동일성 비교(Identity Operator)

Identity Operator

class A {

}

let a = A()
let b = a
let c = A()

a === b // true -> 동일한 주소
a !== b // false

a !== c // true -> 서로 다른 주소

같은 메모리 주소를 갖고 있으면 Identical 하다고 하고, 
같은 값을 갖고 있으면 Equal 하다고 한다.

 

 

* 구조체와 클래스를 비교하는 코드

struct PositionValue {
  var x = 0.0
  var y = 0.0
}

class PositionObject {
  var x = 0.0
  var y = 0.0
}

// 선언과 동시에 기본값을 저장하면 파라미터가 없는 생성자가 자동으로 제공되는데, 이를 기본 생성자(Default Initializer)라고 한다
var v = PositionValue() // x0 y0
var o = PositionObject() // x0 y0

var v2 = v // x0 y0
var o2 = o // x0 y0

v2.x = 12
v2.y = 34

v // x0 y0 -> 복사본이기 때문에 v에는 변화가 없다
v2 // x12 y34

o2.x = 12
o2.y = 34

o // x12 y34 -> 클래스는 새로운 복사본을 생성하지 않고, 참조를 전달(인스턴스가 저장되어 있는 메모리 주소)하기 때문에(원본을 전달) 어떤 변수를 통해 속성을 바꾸더라도 항상 같은 속성을 변경하게 된다
o2 // x12 y34

 

도움이 되셨기를 바라며, 혹시라도 잘못된 부분을 말씀해 주신다면 반영하여 수정하겠습니다!