V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
fffang
V2EX  ›  iDev

Swift 为什么设计 inout 关键字?

  •  
  •   fffang · 2021-05-08 17:19:18 +08:00 · 4161 次点击
    这是一个创建于 1328 天前的主题,其中的信息可能已经有所发展或是发生改变。

    从语言设计的角度上看,有什么必要性么?如果像 OC 那样会发生什么情况?

    8 条回复    2021-05-09 12:32:16 +08:00
    Elethom
        1
    Elethom  
       2021-05-08 17:31:17 +08:00 via iPhone
    OC 也可以丢个 & 进去啊,你这是两个语言都没入门吗,先学会一个再学另一个吧。
    zjw7sky
        2
    zjw7sky  
       2021-05-08 17:36:43 +08:00
    传值、传址
    fffang
        3
    fffang  
    OP
       2021-05-08 17:37:43 +08:00
    @Elethom OC 是可以的。
    可是 OC 中参数 Array 是可以 append 元素的,而 Swift 好像不可以?
    MrKrabs
        4
    MrKrabs  
       2021-05-08 17:46:46 +08:00
    value 和 reference 不一样
    superpeaser
        5
    superpeaser  
       2021-05-08 17:51:23 +08:00
    @fffang OC 的参数 array 传的可变数组的地址
    YYYeung
        6
    YYYeung  
       2021-05-09 00:16:05 +08:00
    Swift 的 inout 表示操作的是指针

    而有一些数据结构,如数组,在 Swift 中是值传递,在 OC 中是引用传递,这会发生什么事?

    在 OC 中,当将一个数组作为一个参数传到另一个函数或方法中,并在该函数体或方法体中,对这个数组 append 一个元素,是没有什么反“直觉”的事发生,一切都很自然

    而在 Swift 中,实际上是 append 到了一个新数组,原来的数组是没有改变的,此时,要实现 OC 的“直觉”效果,就需要用到 inout 了
    0x00ZhouJialei
        7
    0x00ZhouJialei  
       2021-05-09 03:33:06 +08:00
    先说动机 , 引用自 https://docs.swift.org/swift-book/LanguageGuide/Functions.html In-Out Parameters 章节:
    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.

    再说行为, 引用自 https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID545:
    In-out parameters are passed as follows:
    1. When the function is called, the value of the argument is copied.
    2. In the body of the function, the copy is modified.
    3.When the function returns, the copy’s value is assigned to the original argument.
    This behavior is known as copy-in copy-out or call by value result. For example, when a computed property or a property with observers is passed as an in-out parameter, its getter is called as part of the function call and its setter is called as part of the function return.

    多说几句,编译器有可能会把 inout 优化为所谓的传址(call-by-reference),但是官方特意指出开发者们不能依赖这个行为:
    As an optimization, when the argument is a value stored at a physical address in memory, the same memory location is used both inside and outside the function body. The optimized behavior is known as call by reference;
    Write your code using the model given by copy-in copy-out, without depending on the call-by-reference optimization, so that it behaves correctly with or without the optimization

    不严谨的验证方式是,传一个带有 willSet 或者 didSet 的变量到一个 function 的 inout 参数内,就算在 function 内不改变值,willSet 或者 didSet 也会触发
    iOCZ
        8
    iOCZ  
       2021-05-09 12:32:16 +08:00
    不是必须,但是便利吧。常见的是要返回操作成功与否,还要返回处理结果,返回元组当然可以,但是不那么方便。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1212 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:15 · PVG 02:15 · LAX 10:15 · JFK 13:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.