在Swift中,++的确切含义是什么?

4

我正在使用一本面向初学者的书籍学习Swift。有一件事让我困扰,那就是++语法。以下是书中的内容:

var counter = 0
let incrementCounter = {
  counter++
}
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()
incrementCounter()

这本书说计数器是5。

但我在Xcode playground中输入这些代码,结果是4!

我感到困惑。


1
counter++ 可以翻译为 counter = counter + 1,或者 counter += 1。 - Shai
4
请注意,++-- 运算符在 Swift 2.2 中将被弃用,并在 Swift 3 中被移除。 - dfrib
3
不用担心 ++ 和 -- 这两个运算符。它们已被弃用,将在 Swift 3 中被移除。 - user965972
1
因为您在Swift中是“新手”,最好避免使用++和/或--运算符。它们将在未来的Swift语言版本中被移除。相反,建议使用counter += 1。 - user3441734
6个回答

2

x++ 运算符是在多种编程语言中使用的运算符 - C、C++、Java(可以查看C 语言答案以获取相同问题的解答)。

它被称为后增量。它会将给定变量加一,但是在当前表达式求值之后执行。例如:

var x = 1
var y = 2 + x++
// the value of x is now 2 (has been incremented)
// the value of y is now 3 (2 + 1, x has been evaluated before increment)

这与++x(预增量)运算符不同:
var x = 1
var y = 2 + ++x
// the value of x is now 2 (has been incremented)
// the value of y is now 4 (2 + 4, x has been evaluated after increment)

请注意,在Swift的下一个版本中,该运算符将被删除,因此您不应再使用它。

最好只写x += 1而不是带有副作用的复杂表达式。


2
在您对“incrementCounter”闭包进行五次调用后,“counter”的值将为5,但是每次对“incrementCounter”的调用的返回值似乎会滞后一步。正如Sulthan在他的回答中所写的那样,这是由于x ++ 是一个后缀递增运算符:表达式的结果将在递增之前返回。
var x = 0
print(x++) // 0
print(x)   // 1

此外,正如我在上面的评论中所写的,你不应该使用++--运算符,因为它们将会在Swift 2.2中被弃用,并且在Swift 3中被移除。然而,如果你对后缀递增和前缀递增运算符的细节感兴趣,你可以在SO上找到标记为其他语言但涵盖同一主题的好答案,例如:
  • ++i和i++之间有什么区别?

  • 值得一提的是,有一个与Swift > 2.1相关的观点,但这并不特别涉及到++运算符。当您将闭包incrementCounter初始化为时。
    var someOne : Int = 0
    let incrementCounter = {
        someInt
    }
    

    这句话的意思是:闭包的类型被隐式推断为 () -> Int,它是一个不带参数但返回类型为 Int 的闭包。
    let incrementCounter: () -> Int = {
        return someInt
    }
    

    因此,你在游乐场上看到的似乎是调用 incrementCounter 闭包的未使用(未分配)返回值;也就是表达式 incrementCounter() 的结果。

    enter image description here

    然而,在你的 playground 的右侧块中,counter 的值实际上从未被打印出来(除非你编写一行代码,其中该行表达式的结果是 counter)。


    dfri,你喜欢将一元++和/或--从语言中移除的决定吗?请看看我的“答案”以及对它的注释 :-) - user3441734
    @user3441734,你提出了一些有趣的观点。然而,希望在未来的Swift版本中,闭包的类型推断会变得更好(例如,你的第三个代码块应该能够编译并推断闭包为() -> Int)。个人而言,我喜欢利用副作用和表达式,包括例如++,但我完全理解Swift决定删除它们的原因,因为Swift的通用代码安全性是一个标志性特征,我相信他们希望在其范围内也包括对逻辑错误的安全性。在这种情况下,当被不熟练的程序员使用或阅读代码时,++--会带来一些危险。 - dfrib

    2
    “post-increment” 和 “post-decrement” 操作符将其操作数的值增加(或减少)1,但表达式的值是操作数在增量(或减量)操作之前的原始值。因此,在看到 playground 时,计数器的当前值被打印出来了。

    playground

    但是在函数评估之后,计数器的值会发生变化,您可以在下一行看到更新后的值。

    2

    在标识符前使用++和--会加/减1,然后返回其值。
    在标识符后使用++和--会返回其值,然后加/减1。

    在Swift 3.0中已被移除,但您可以重新添加它们:

    prefix operator --
    prefix operator ++
    postfix operator --
    postfix operator ++
    
    prefix func ++(_ a : inout Int) -> Int {
        a += 1
        return a
    }
    prefix func --(_ a : inout Int) -> Int {
        a -= 1
        return a
    }
    postfix func ++(_ a: inout Int) -> Int {
        defer { a += 1 }
        return a
    }
    postfix func --(_ a: inout Int) -> Int {
        defer { a -= 1 }
        return a
    }
    
    var a = 11
    print(a++) // 11
    print(a)   // 12
    
    var b = 5
    print(--b) // 4
    print(b) // 4
    
    

    1

    虽然有很多答案,而且它们都很清晰,但我添加了这个片段来向您展示如何使用“新”语法替换您的代码,其中++和--已被弃用。首先是您自己的代码。

    var counter = 0
    let incrementCounter = {
        counter++
    }
    let i0 = incrementCounter() // 0
    let i1 = incrementCounter() // 1
    // .....
    

    如何在未来的Swift语法中重写它?让我们尝试推荐的替代方法...
    var counter = 0
    let ic = {
        counter += 1
    }
    let i0 = ic() // () aka Void !!!
    let i1 = ic() // ()
    

    但是现在ic()的结果是Void!嗯...好的,下一次尝试可能会像这样
    var counter = 0
    let ic = {
        counter += 1
        return counter
    }
    

    但是现在代码编译时出错了:无法推断当前上下文中的闭包返回类型 :-),因此我们必须声明它(在原始版本中不需要)

    var counter = 0
    let ic:()->Int = {
        counter += 1
        return counter
    }
    let i0 = ic() // 1
    let i1 = ic() // 2
    // .....
    

    它可以工作,但结果不同。这是因为在原始代码中使用了++运算符作为后缀递增运算符。因此,我们需要对我们的“新”版本进行另一种调整。

    var counter = 0
    let ic:()->Int = {
        let ret = counter
        counter += 1
        return ret
    }
    let i0 = ic() // 0
    let i1 = ic() // 1
    // .....
    

    是的,我希望在未来版本的Swift中也能看到我熟悉的一元运算符++和/或--。


    0
    你正在做的是后置递增。
    首先学习一下前置和后置递增之间的区别:
    1. 在后置递增中,增量计数器包含递增后的值(即 5),但如果我们返回它,它将包含旧值(即 4)。 2. 在前置递增中,值和返回值都会被递增。
    现在让我们看看你的代码,
    counter++ 会创建一个副本,增加 counter 的值,并返回该副本(旧值)。
    因此,如果你打印 counter,它将具有递增后的值(即 5),但是,如果你返回 counter(即使用 incrementCounter 这样做),它将包含旧值(即 4)。
    这就是为什么 incrementCounter 只显示到 4 的原因。

    检查输出 输入图像描述 解决方案:

    counter++更改为++counter

    检查输出 输入图像描述


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接