Swift

2. iOS 값타입(Value Type)과 참조타입(Reference Type)

Daesiker 2022. 7. 5. 11:42
반응형

2-1. 개요

타입은 데이터를 전달하는 방식에 따라 값타입(Value Type)과 참조타입(Reference Type)으로 나뉜다.

값 타입(Value Type)

  • Struct
  • Enum
  • Tuple

참조 타입(Reference Type)

  • Class
  • Closure

대표적인 값타입으로는 구조체, 열거형, 튜플 등이 있고 참조타입은 클래스나 함수 등이 있다. 여기서 Struct와 Class를 이용해서 메모리에 어떻게 할당되고 해제되는지 알아볼 예정이다.


2-2. Class

-Source Code

class Human {
    var age:Int
    var name:String

    init(_ age: Int, _ name: String) {
        self.age = age
        self.name = name
        print("\(name) init")
    }

    deinit {
        print("\(name) deinit")
    }

}

var human1:Human? = Human(28, "Daesik")
var human2 = human1
human2?.age = 27

print(human1?.age ?? 0)
print(human2?.age ?? 0)

human1 = nil
human2 = nil

소스 코드를 분석해보면 age, name이란 멤버를 가진 Human 클래스를 만들었고 메모리에 할당, 해제될 때 확인하기 위해 출력문을 작성하였다. 그리고 human1이라는 옵셔널 변수 인스턴스를 만들고 대입 연산을 통해 human2라는 인스턴스를 만들었다. 그 다음 human2의 age 값을 바꾸고 human1과 human2의 age를 출력한뒤 2개의 인스턴스를 nil로 초기화 하였다.

-Console

Daesik init
27
27
Daesik deinit

결과 값을 보면 3가지 사실을 알 수 있다.

  • human1과 human2라는 2개의 인스턴스를 생성했지만 init은 1번만 됐다.
  • human2의 age값을 바꿨는데 human1도 같이 바뀌었다.
  • 2개의 인스턴스를 nil로 초기화 하였지만 deinit은 1번만 됐다.

이것을 통해 2개의 인스턴스는 값을 공유한다는 것을 알 수 있다. 참조타입의 인스턴스를 초기에 생성을 하면 heap 메모리에 인스턴스의 값이 메모리에 할당되고 stack메모리에 heap메모리에 할당된 공간의 주소값이 저장된다. 그리고 해당 인스턴스를 대입연산을 통해 값을 복사한다면 heap메모리에 또 다른 새로운 값이 할당되는 것이 아니라 스택메모리에 해당 값이 들어가있는 heap 메모리에 주소값이 할당이 되는 것이다. 그리고 heap메모리의 값을 참조하는 스택 메모리가 1개도 없을 경우 그 때 iOS에서는 자동으로 heap메모리의 값이 해제가 된다.


2-3. Struct

-Source Code

struct Human {
    var age:Int
    var name:String

    init(_ age: Int, _ name: String) {
        self.age = age
        self.name = name
        print("\(self.name) init")
    }

}

var human1:Human? = Human(28, "Daesik")
var human2 = human1

human2?.age = 29

print(human1!.age)
print(human2!.age)

 

-Console

Daesik init
28
29

마찬가지로 1개의 human1 만들고 대입 연산을 통해 human2를 생성하였고 human2의 age값을 바꾼 뒤 비교해 보았다. 이번엔 human1과 human2의 age값이 서로 다른 것을 알 수 있다.

값 타입인 경우에는 바로 스택 영역에 데이터의 값을 할당을 하고 대입연산을 통해 복사를 하게 되면 해당 인스턴스의 주소값을 가져오는 것이 아니라 이 값 자체를 그대로 가져오게 된다. 그래서 대입연산을 하게 되면 서로 각자 다른 메모리 공간에 할당되기 때문에 서로 값을 공유하지 않는 것이다.

또한 구조체는 클래스처럼 상속이 되지 않고 deinit으로 할당해제가 불가능하다.


2-4. 타입별 let, var

이걸 통해서 또 하나 알 수 있는 것은 Struct으로 만든 let 인스턴스는 안에 있는 멤버의 값도 변경을 못하지만 Class로 만든 let 인스턴스는 해당 멤버가 var이라면 값을 변경할 수 있다. 이 이유는 인스턴스를 생성할 때 let과 var의 기준은 스택 영역이기 때문이다. struct의 경우 값도 스택 메모리에 저장되있기 때문에 let이라면 멤버가 변수로 취급되어 있어도 못바꾸는 것이고 class는 스택메모리에는 주소값만 저장이 되어 있기 때문에 주소값만 바꿀 수 없고 실제 값은 heap에 있어서 멤버가 var로 선언이 되어 있다면 바꿀 수 있다.

반응형