code

입출력 매개 변수를 언제 사용합니까?

codestyles 2020. 11. 13. 08:12
반응형

입출력 매개 변수를 언제 사용합니까?


클래스 또는 기본 유형을 함수에 전달할 때 매개 변수에 대한 함수의 변경 사항은 클래스 외부에 반영됩니다. 이것은 기본적으로 inout매개 변수가 수행해야하는 것과 동일 합니다.

inout 매개 변수의 좋은 사용 사례는 무엇입니까?


inout즉, 지역 변수를 수정하면 전달 된 매개 변수도 수정됩니다. 이것이 없으면 전달 된 매개 변수는 동일한 값으로 유지됩니다. 사용할 때 참조 유형을 생각 inout하고 사용하지 않고 값 유형 을 생각 하십시오.

예를 들면 :

import UIKit

var num1: Int = 1
var char1: Character = "a"

func changeNumber(var num: Int) {
    num = 2
    print(num) // 2
    print(num1) // 1
}
changeNumber(num1)

func changeChar(inout char: Character) {
    char = "b"
    print(char) // b
    print(char1) // b
}
changeChar(&char1)

좋은 사용 사례는 swap전달 된 매개 변수를 수정하는 함수입니다.

스위프트 3+ 참고 : 스위프트 3부터가inout키워드는 와야 콜론과 형식 앞에. 예를 들어, Swift 3+는 이제 func changeChar(char: inout Character).


에서 선언 - 인 - 아웃 파라미터 : 애플 언어 참조 :

최적화로, 인수가 메모리의 물리적 주소에 저장된 값인 경우 함수 본문 내부와 외부에서 동일한 메모리 위치가 사용됩니다. 최적화 된 동작을 참조에 의한 호출이라고합니다. 카피 인 카피 아웃 모델의 모든 요구 사항을 충족하는 동시에 카피 오버 헤드를 제거합니다 . 카피 인 카피 아웃과 참조에 의한 호출 사이의 동작 차이에 의존하지 마십시오.

다소 메모리 측면에서 큰 값 유형을 인수로 사용하고 (예 : 큰 구조 유형) 동일한 유형을 반환하는 함수가 있고 마지막으로 함수 반환이 항상 호출자 인수를 대체하는 데 사용되는 경우 다음 inout과 같습니다. 연관된 함수 매개 변수로 선호합니다.

아래의 예를 살펴 보겠습니다. 주석이 여기 inout에 일반 type-in-return-type 함수 를 사용 하는 이유를 설명 합니다.

struct MyStruct {
    private var myInt: Int = 1

    // ... lots and lots of stored properties

    mutating func increaseMyInt() {
        myInt += 1
    }
}

/* call to function _copies_ argument to function property 'myHugeStruct' (copy 1)
   function property is mutated
   function returns a copy of mutated property to caller (copy 2) */
func myFunc(var myHugeStruct: MyStruct) -> MyStruct {
    myHugeStruct.increaseMyInt()
    return myHugeStruct
}

/* call-by-reference, no value copy overhead due to inout opimization */
func myFuncWithLessCopyOverhead(inout myHugeStruct: MyStruct) {
    myHugeStruct.increaseMyInt()
}

var a = MyStruct()
a = myFunc(a) // copy, copy: overhead
myFuncWithLessCopyOverhead(&a) // call by reference: no memory reallocation

또한 위의 예에서 ---- 메모리 문제를 무시 ---- inout우리 코드를 읽는 사람에게 우리가 함수 호출자 인수 (함수 &에서 인수 앞에 앰퍼샌드로 암시 적으로 표시됨)를 변경하고 있음을 알리는 좋은 코드 관행으로 선호 될 수 있습니다. 요구). 다음은 이것을 아주 깔끔하게 요약합니다.

함수가 매개 변수 값을 수정하도록하고 함수 호출이 종료 된 후에도 이러한 변경 사항을 유지하려면 해당 매개 변수를 대신 in-out 매개 변수로 정의하십시오.

에서 - 인 - 아웃 매개 변수 기능 : 애플 언어 가이드 .


자세한 내용과 inout메모리에서 실제로 처리되는 방법 (이름 copy-in-copy-out은 다소 오해의 소지가 있습니다 ...)-위의 언어 가이드 링크에 추가로 ---- 다음 SO 스레드를 참조하십시오.


(추가 편집 : 추가 메모)

위의 Lucas Huang이 수락 한 답변에 주어진 예는 inout인수를 사용하는 함수 범위에서 인수로 전달 된 변수에 액세스 하려고합니다 inout. 이것은 권장되지 않으며 ref 언어에서하지 않도록 명시 적으로 경고합니다.

원래 인수가 현재 범위에서 사용 가능하더라도 in-out 인수로 전달 된 값에 액세스하지 마십시오 . 함수가 반환되면 원본에 대한 변경 사항을 복사본 값으로 덮어 씁니다. 변경 사항을 덮어 쓰지 않도록하기 위해 참조 별 호출 최적화 구현에 의존하지 마십시오 .

이제이 경우 액세스는 "오직"변경할 수 없습니다 (예 :) print(...). 그러나 이와 같은 모든 액세스는 관례 상 피해야합니다.

댓글 작성자의 요청에 따라 "인-아웃 인수로 전달 된 값"으로 실제로 아무것도하지 말아야하는 이유를 설명하는 예제를 추가하겠습니다 .

struct MyStruct {
    var myStructsIntProperty: Int = 1

    mutating func myNotVeryThoughtThroughInoutFunction (inout myInt: Int) {
        myStructsIntProperty += 1
        /* What happens here? 'myInt' inout parameter is passed to this
           function by argument 'myStructsIntProperty' from _this_ instance
           of the MyStruct structure. Hence, we're trying to increase the
           value of the inout argument. Since the swift docs describe inout 
           as a "call by reference" type as well as a "copy-in-copy-out"
           method, this behaviour is somewhat undefined (at least avoidable).

           After the function has been called: will the value of
           myStructsIntProperty have been increased by 1 or 2? (answer: 1) */
        myInt += 1
    }

    func myInoutFunction (inout myInt: Int) {
        myInt += 1
    }
}

var a = MyStruct()
print(a.myStructsIntProperty) // 1
a.myInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 2
a.myNotVeryThoughtThroughInoutFunction(&a.myStructsIntProperty)
print(a.myStructsIntProperty) // 3 or 4? prints 3.

따라서이 경우 입력은 참조가 아닌 복사 복사로 동작합니다. 언어 참조 문서에서 다음 문장을 반복하여 요약합니다.

카피 인 카피 아웃과 참조에 의한 호출 사이의 동작 차이에 의존하지 마십시오.


Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake. If you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.

see image below for Description


inout parameter allow us to change the data of a value type parameter and to keep changes still after the function call has finished.


If you work with classes then, as you say, you can modify the class because the parameter is a reference to the class. But this won't work when your parameter is a value type (https://docs.swift.org/swift-book/LanguageGuide/Functions.html - In-Out Parameters Section)

One good example of using inout is this one (defining math for CGPoints):

func + (left: CGPoint, right: CGPoint) -> CGPoint {
  return CGPoint(x: left.x + right.x, y: left.y + right.y)
}

func += (left: inout CGPoint, right: CGPoint) {
  left = left + right
}

Basically it is useful when you want to play with addresses of variable its very useful in data structure algorithms


when use inout parameter swift 4.0 Work

class ViewController: UIViewController {

    var total:Int = 100

    override func viewDidLoad() {
        super.viewDidLoad()
        self.paramTotal(total1: &total)
    }

    func paramTotal(total1 :inout Int) {
        total1 = 111
        print("Total1 ==> \(total1)")
        print("Total ==> \(total)")
    }
}

참고URL : https://stackoverflow.com/questions/34486052/when-to-use-inout-parameters

반응형