1. 메모리 할당
- 값 타입과 참조 타입의 가장 큰 차이점중 하나나
- 값 타입 -> 스택 영역 할당
- 참조 타입 -> 힙 영역 할당
2. 스택 할당
- 한 방향으로 데이터를 넣고 빼는 단순한 구조
- 스택 포인터를 사용하여 빠르게 접근
- 많은 시간을 필요로 하지 않음
3. 힙 할당
- 할당할 때마다 적절한 메모리 공간이 있는지 확인한 후 할당
- 많은 오버헤드 발생
4. String
- 스위프트에서 String은 값타입
- 문자들은 Character 타입으로 힙 영역에 간접적 저장이 되어 힙 할당이 발생
5. String 힙 할당 피하기
enum Emotion { case Happy, sad, angry }
enum Species { case human, bear, cat }
var cachedEmoji = [String: UIImage]()
func generateEmoji(_ emotion: Emotion, _ species: Species) -> UIImage {
let key = "\(emotion):\(species)"
if let image = cachedEmoji[key] {
return image
}
}
- 위 코드는 Emoji / Species 전달인자에 따른 이모티콘 이미지 반환
- generateEmoji() 함수를 보면 String 타입의 key 상수를 cachedEmoji의 키값으로 사용
- String은 값 타입이지만 힙 할당이 발생
- 함수 호출시 마다 힙 할당이 발생하여 메모리 사용량이 많아짐
- 다음과 같이 구조체를 작성
struct Attributes: Hashable {
var emotion: Emotion
var species: Species
}
- 구조체는 값 타이기 때문에 프로퍼티 모두 enum 타입으로 Attributes 구조체 인스턴스 생성시 힙 할당이 아닌 스택 할당이 발생
- 여기서 Hashable은 사용자 정의 타입을 컬렉션에 사용하기 위해 필요한 프로토콜로 딕셔너리 키값으로 사용하기 위해 사용
- 다음과 같이 수정
enum Emotion { case happy, sad, angry }
enum Species { case human, bear, dragon }
var cachedEmoji = [Attributes: UIImage]()
func generateEmoji(_ emotion: Emotion, _ species: Species) -> UIImage {
let key = Attributes(emotion: emotion, species: species)
if let image = cachedEmoji[key] {
return image
}
}