https://bangul-domato.tistory.com/44
InOut 매개변수
- 함수 내부에서 발생하는 사건은 함수 외부에 영향을 미칠 수 없음
- 단순히 같은 값을 가지고 있을 뿐, 둘은 단절된 서로 다른 객체
var cnt = 30
func autoIncrement(value: Int) -> Int {
var value = value
value += 1
return value
}
print(autoIncrement(value: cnt)) // 함수 내부의 변수 value 값 : 31
print(cnt) // 함수 외부에서 정의된 cnt 값 : 30
- 외부에서 입력한 인자값(cnt)이 직접 함수 내부로 전달되는 것이 아니라 그 값이 복사된 다음 전달되기 때문
- 인자값으로 전달된 cnt와 매개변수 value는 서로 다른 변수
- inout 키워드를 활용해 함수 내부에서 수정된 인자값을 함수 외부까지 전달할 수 있음
func foo(paramCount: inout Int) -> Int {
paramCount += 1
return paramCount
}
var count = 30
print(foo(paramCount: &count)) // 함수 내부의 변수 paramCount 값 : 31
print(count) // 외부에서 정의된 변수 count 값 : 31
// 상수는 inout 매개변수에 인자값으로 전달할 수 없음
let count1 = 30
foo(paramCount: &count1) // (X)
// literal은 inout 매개변수에 인자값으로 전달할 수 없음
foo(paramCount: &30) // (X)
- inout 키워드가 붙은 매개변수는 인자값 자체를 함수 내부로 전달 → 인자값으로 사용된 변수와 동일한 객체
- inout : 값이 저장된 메모리 주소를 전달 (C의 pointer)
- inout 매개변수에 들어갈 인자값에는 주소 추출 연산자 &를 붙여주어야 정상적으로 전달함
- & : 변수나 상수 앞에 붙어서 값이 저장된 메모리 주소를 읽어오는 역할
* 값에 의한 전달 : 값을 복사하여 전달
- 내부적으로 복사를 통해 생성된 새로운 변수나 상수를 이용하여 함수의 기능을 실행
→ 인자값의 수정이 발생하더라도 원본 데이터에 영향 없음
* 참조(Reference)에 의한 전달 : 주소를 전달하는 것
- 값이 저장된 주소가 전달 → 인자값을 저장하고 있는 객체 자체가 전달
- 외부의 인자값을 직접 참조하므로 함수 내부의 인자값이 수정되면 외부 인자값 원본에도 반영
- 예외적으로 Class로 구현된 인스턴스 inout 키워드를 사용하지 않아도 항상 참조에 의해 전달
→ 함수의 인자값으로 전달한 클래스 인스턴스는 함수 내부에서 값이 수정되면 원본 객체에도 영향
- inout 키워드가 붙은 매개변수는 변수만 인자값으로 사용 가능
- 상수, 리티럴은 전달 대상이 될 수 없음
- 함수 내부에서 원본 객체에 직접 값을 수정해야 하기 때문
변수 생존 범위와 생명 주기
변수의 Scope(생존범위) : 전역변수와 지역변수
- 전역변수(Global variable)
- 프로그램의 최상위 레벨에서 작성
- 일반적으로 프로그램 내 모든 위치에서 참조 가능
- 특별한 경우를 제외하곤 프로그램 종료 전까지는 삭제되지 않음
- 지역변수(Local variable)
- 특정 범위 내에서만 참조하거나 사용할 수 있는 변수
- 조건절, 함수 구문 등 특정 실행 블록 내부에서 선언된 변수 → 선언된 블록 범위 안에서만 변수 참조가 가능함
- 변수의 생명주기(Life Cycle) : 선언된 블록이 실행되면서 생겨났다가 실행 블록이 끝나면 제거
// 지역변수 1.
do {
do {
var ccnt = 3 // 중첩된 do {} 안에서만 생존
ccnt += 1
print(ccnt) // (1) 4
}
ccnt += 1
print(ccnt) // (2) error : "Use of unresolved identifier 'ccnt'"
// 선언되지 않은 변수 호출 시 발생 -> ccnt가 선언된 블록 바깥에서 사용되었기 때문(변수 범위의 바깥)
}
// 지역변수 2.
do {
var ccnt = 0 // do {}(상위블록) 안에서 생존 가능 -> 중첩된 do {}(하위블록) 에서도 사용 가능
// 변수가 생성된 블록이 아닌 다른 블록에서 사용하려면 반드시 초기화되어 있어야 함
// 하나의 블록에서 다른 블록으로 참조에 의한 전달 과정이 일어나는 것
// 변수가 초기화되지 않았다면 메모리를 할당받지 못한 상태이므로 주소값도 존재 X -> 오류 발생
do {
ccnt = 3
print(ccnt) // (1) 3
}
ccnt += 1
print(ccnt) // (2) 4
}
// 전역변수
var count = 30
// 최상위 블록에서 선언된 변수이므로 하위 블록인 함수 내부에서도 접근 가능함
func foo() -> Int {
count += 1
return count
}
foo() // 31
// 값이 참조 방식으로 전달되므로 블록 내부에서 값을 변경하면 외부에도 그대로 적용 가능
// 수정 또는 값의 접근 가능
// 전역 변수와 지역 변수의 이름과 타입이 동일한 경우
var count = 30 // (2) 전역변수 count
func foo(count: Int) -> Int {
var count = count // (1) 지역변수 count
count += 1
return count
}
print(foo(count: count)) // (1) 함수 내부의 변수 count 값 : 31
print(count) // (2) 외부에서 정의된 변수 count 값 : 30
- 외부와 내부에 같은 이름의 변수가 존재한다면 내부에서 선언된 변수는 외부와 상관없이 새롭게 생성됨
* 변수 검색 순서(컴파일러)
함수 내부에서 정의된 변수 → 함수 외부에서 정의된 변수 → 글로벌 범위에서 정의된 변수 → import된 라이브러리 범위
[Day17] searchable (0) | 2024.05.21 |
---|---|
[Day16] Function: 함수의 중첩과 클로저 (1) | 2024.05.16 |
[Day14] Function : 매개변수(3) (0) | 2024.05.01 |
[Day12, 13] Function : 함수의 기본 개념(1), (2) (0) | 2024.04.23 |
[Day11] Optional(2) (0) | 2024.04.22 |
댓글 영역