본문 바로가기
공부하기/Swift

Swift) 값 타입과 참조 타입 그리고 클래스와 구조체 (Value type & Reference type, Class & Struct)

by hyunjicraft 2021. 1. 5.

값 타입과 참조 타입

값 타입

변수를 할당하면 스택 영역에 값이 저장된다.

변수를 복사한 후 복사본을 변경하더라도 원본에 영향을 주지 않는다.

힙 영역을 사용하지 않고 레퍼런스 카운팅이 필요하지 않다.

 

참조 타입

스택 영역에는 포인터(레퍼런스)만 할당되고 실제 데이터는 힙 영역에서 할당된다.

변수를 복사하더라도 하나의 값을 가리키고 있기 때문에 복사본과 원본이 모두 같은 값을 갖는다.

변수를 복사하더라도 레퍼런스 카운트만 +1되고 실제 값이 복사되지는 않는다.

 

 

Swift의 Class와 Struct는 생김새와 사용법이 유사하다.

구조체는

1. 값 타입이다.

2. 상속이 불가능하다.

3. 생성자를 구현하지 않아도 default initializer를 사용할 수 있다.

 

struct Car {
    var name : String
    var color : String
}

let car1 = Car(name: "i7", color: "Black")
print(car1)
//Car(name: "i7", color: "Black")

var car2 = car1
print(car2)
//Car(name: "i7", color: "Black")

car2.name = "i9"
print(car2)
print(car1)
//Car(name: "i9", color: "Black")
//Car(name: "i7", color: "Black")
//car2의 프로퍼티를 변경해도 원본인 car1의 프로퍼티 값은 변경되지 않았다.

 

클래스는

1. 참조 타입이다.

2. 생성자를 구현해야만 사용할 수 있다.

class Student {
    var name : String
    var age : Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func print() {
        print("name: \(name), age: \(age)")
    }
    //기본 print() 함수를 사용하면 주소값이 출력되기 때문에 직접 함수로 구현함.
}

let std1 = Student(name: "Peter", age: 17)
std1.print()
//name: Peter, age: 17

let std2 = std1
std2.print()
//name: Peter, age: 17

std2.name = "Ken"
std2.print()
std1.print()
//name: Ken, age: 17
//name: Ken, age: 17
//std2의 프로퍼티 값을 변경하면 원본인 std1의 프로퍼티 값도 함께 변경된다.

 

* Swift의 Enum, Array, String, Dictionary, Set, Tuple도 Struct와 동일한 값 타입이다

* Swift의 Function과 Closure는 Class와 동일한 참조 타입이다.

 

차이를 구분하지 않고 써도 무리가 없는 경우가 많지만 개념을 확실히 알고 있다면 도움이 될 것 같다.

 

참고) 프로그램 실행 순서와 메모리 영역

댓글