- Value Type (structure(Int, String, Bool, Double, Array, Dictionary, …), enumeration, tuple)
value type은 변수(var) 혹은 상수(constant)에 할당하거나 함수에 전달할 때, type의 value가 복사된다.
변수 A의 객체를 변수 B에 할당한다면 새로운 복사본이 B에 할당된 것이므로 A와 B는 전혀 다른 instance다.
즉, 같은 값을 가진 다른 인스턴스
→ B 객체의 값을 바꾸는 것은 A에 영향을 미치지 않는다.
- Reference Type (class)
reference type은 변수(var) 혹은 상수(constant)에 할당하거나 함수에 전달할 때, 같은 인스턴스를 사용한다.
변수 A의 객체를 변수 B에 할당한다면 같은 인스턴스를 참조하는 것이다. (동일 인스턴스에 다른 이름 두 개)
→ 같은 인스턴스를 참조하고 있으므로 A 혹은 B에서 값을 변경하면 모두 영향을 미침.
copy on write이라는 개념은 “메모리 액세스 부담”을 줄이기 위해서 나왔다.
메모리에 기본 데이터를 통으로 새로운 복사본을 만들지 않고, class가 동작하는 것처럼 원본 배열과 동일한 메모리 주소를 가리키도록 배열의 복사본을 생성한다. 그리고 만약 새로운 배열을 수정한다면, 그때서야 새로운 메모리 주소가 생성된다.
그러므로 새로운 배열 데이터가 수정되지 않는다면 배열의 새로운 메모리는 생성되지 않고 같은 reference만 가리키게 된다.
struct Apple {
var number: Int = 2
var price: Int = 100
}
func address(object: UnsafeRawPointer) -> String {
let address = Int(bitPattern: object)
return NSString(format: "%p", address) as String
}
var basket = [Apple()]
var anotherBasket = basket
print(address(object: &basket))
print(address(object: &anotherBasket))
//좀 더 쉽게 공부하기 위해 변경한 간단한 코드
결과를 보기 전에 먼저 생각해 보자!
배열 변수 basket에 구조체 Apple() 객체를 할당했고, 변수 anotherBasket에 basket을 할당했다.
struct는 value type으로 copy on write 한다.
위에서 말했듯이 copy on write은 연산 비용을 최적화하기 위해 수정 전까지는 같은 reference를 가리킨다고 했다. 그러므로 출력된 두 변수의 주소값은 동일할 것이다!
output:
0x600000c00bc0
0x600000c00bc0
→ 구조체가 새로운 복사본을 만들었지만 이는 객체에 대한 전체 복사가 아니고 우선 같은 메모리 주소를 가리키도록 한다.
struct Apple {
var price: Int = 100
}
func address(object: UnsafeRawPointer) -> String {
let address = Int(bitPattern: object)
return NSString(format: "%p", address) as String
}
var basket = [Apple()]
var anotherBasket = basket
print(address(object: &basket))
print(address(object: &anotherBasket))
anotherBasket[0].price = 400
print("===============")
print(address(object: &basket))
print(address(object: &anotherBasket))
이 코드는 anotherBasket를 수정한 것이다. anotherBasket에 들어있는 Apple의 number를 변경했다.
수정했으니 이제야 a2에 대한 새로운 복사본을 만들어 낸다
output:
0x600000c00bc0
0x600000c00bc0
===============
0x600000c00bc0
0x600000c00c50 //📌 주소값 변경!
수정 전까지만 해도 두 변수는 같은 memory location을 가리켰는데 anotherBasket을 수정하니까 다른 memory location을 가리키기 시작했다. 이게 바로 Swift에서 copy on write 하는 방법이다.
그렇다면,, 원본 값을 수정해도??
struct Apple {
var price: Int = 100
}
func address(object: UnsafeRawPointer) -> String {
let address = Int(bitPattern: object)
return NSString(format: "%p", address) as String
}
var basket = [Apple()]
var anotherBasket = basket
print(address(object: &basket))
print(address(object: &anotherBasket))
basket[0].price = 400
print("===============")
print(address(object: &basket))
print(address(object: &anotherBasket))
output:
0x600000c08b90
0x600000c08b90
===============
0x600000c08c20 //📌 주소값 변경!
0x600000c08b90
당연함. value type이라 다른 애들임
+ Swift는 커스텀 객체에 대해서도 copy on write를 적용할 수 있도록 해준다.
[참고 사이트]
https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
https://medium.com/@iostpointblog/what-is-copy-on-write-18701742e60c
'Swift' 카테고리의 다른 글
[Swift] DateFormatter 털어보기 (1/2) (0) | 2024.06.17 |
---|---|
[Swift] 고차 함수를 알아보자! (1) | 2023.11.25 |
[Swift] 10진수 ↔ 2진수 변환하기 (0) | 2022.12.27 |
[Swift] 문자열과 문자(Strings & Characters) (2/2) (0) | 2022.02.13 |
[Swift] 문자열과 문자(Strings & Characters) (1/2) (0) | 2022.02.13 |