146

我正在查看 Xcode 7.3 笔记,我注意到了这个问题。

++ 和 -- 运算符已被弃用

有人可以解释为什么它被弃用吗?我是对的,现在在新版本的 Xcode 中你将使用它来代替++这个x += 1

例子:

for var index = 0; index < 3; index += 1 {
    print("index is \(index)")
}

警告截图

4

12 回答 12

220

Swift 的创造者 Chris Lattner在这里给出了完整的解释。我总结一下几点:

  1. 这是您在学习 Swift 时必须学习的另一个功能
  2. 不短于x += 1
  3. Swift 不是 C。不应该仅仅为了取悦 C 程序员而把它们带过来
  4. 它的主要用途是 C 风格的 for 循环:for i = 0; i < n; i++ { ... },Swift 有更好的替代品,比如for i in 0..<n { ... }(C 风格的 for 循环也将退出
  5. 阅读和维护可能很棘手,例如 or 的值是x - ++x什么foo(++x, x++)
  6. 克里斯拉特纳不喜欢它。

对于那些感兴趣的人(并且为了避免链接失效),Lattner 用他自己的话来说的原因是:

  1. 这些运算符增加了学习 Swift 作为第一门编程语言的负担——或者任何其他你还不知道这些运算符来自不同语言的情况。

  2. 它们的表达优势很小——x++ 并不比 x += 1 短很多。

  3. Swift 已经偏离了 C,因为 =、+= 和其他类似赋值的操作返回 Void(出于多种原因)。这些运算符与该模型不一致。

  4. Swift 具有强大的功能,可以消除您在其他语言的 C 风格 for 循环中使用 ++i 的许多常见原因,因此这些在编写良好的 Swift 代码中相对较少使用。这些功能包括 for-in 循环、范围、枚举、映射等。

  5. 实际使用这些运算符的结果值的代码对于代码的读者/维护者来说通常是令人困惑和微妙的。他们鼓励“过于棘手”的代码,这些代码可能很可爱,但很难理解。

  6. 虽然 Swift 有明确定义的评估顺序,但任何依赖于它的代码(如 foo(++a, a++))即使定义明确也是不可取的。

  7. 这些运算符适用于相对较少的类型:整数和浮点标量,以及类似迭代器的概念。它们不适用于复数、矩阵等。

最后,这些都没有达到“如果我们还没有这些,我们会将它们添加到 Swift 3 中吗?”的标准。

于 2016-02-02T16:21:48.593 回答
41

我意识到这个评论并没有回答这个问题,但是可能有人在寻找如何让这些操作员继续工作的解决方案,这样的解决方案可以在底部找到。

我个人比较喜欢++--运营商。我不同意他们棘手或难以管理的观点。一旦开发人员了解了这些运算符的作用(我们谈论的是非常简单的东西),代码应该非常清晰。

在解释为什么不推荐使用运算符时提到它们的主要用途是 C 风格的 for 循环。我不了解其他人,但我个人根本不使用 C 风格的循环,还有很多其他地方或情况下++or--运算符很有用。

我还想提一下,它varName++返回一个值,因此它可以在returnwhile中使用,但varName += 1不能。

对于任何想让这些操作员在这里工作的人来说,解决方案是:

prefix operator ++ {}
postfix operator ++ {}

prefix operator -- {}
postfix operator -- {}


// Increment
prefix func ++(inout x: Int) -> Int {
    x += 1
    return x
}

postfix func ++(inout x: Int) -> Int {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: UInt) -> UInt {
    x += 1
    return x
}

postfix func ++(inout x: UInt) -> UInt {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: Int8) -> Int8 {
    x += 1
    return x
}

postfix func ++(inout x: Int8) -> Int8 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: UInt8) -> UInt8 {
    x += 1
    return x
}

postfix func ++(inout x: UInt8) -> UInt8 {
    x += 1
    return (x - 1)
}
prefix func ++(inout x: Int16) -> Int16 {
    x += 1
    return x
}

postfix func ++(inout x: Int16) -> Int16 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: UInt16) -> UInt16 {
    x += 1
    return x
}

postfix func ++(inout x: UInt16) -> UInt16 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: Int32) -> Int32 {
    x += 1
    return x
}

postfix func ++(inout x: Int32) -> Int32 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: UInt32) -> UInt32 {
    x += 1
    return x
}

postfix func ++(inout x: UInt32) -> UInt32 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: Int64) -> Int64 {
    x += 1
    return x
}

postfix func ++(inout x: Int64) -> Int64 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: UInt64) -> UInt64 {
    x += 1
    return x
}

postfix func ++(inout x: UInt64) -> UInt64 {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: Double) -> Double {
    x += 1
    return x
}

postfix func ++(inout x: Double) -> Double {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: Float) -> Float {
    x += 1
    return x
}

postfix func ++(inout x: Float) -> Float {
    x += 1
    return (x - 1)
}

prefix func ++(inout x: Float80) -> Float80 {
    x += 1
    return x
}

postfix func ++(inout x: Float80) -> Float80 {
    x += 1
    return (x - 1)
}

prefix func ++<T : _Incrementable>(inout i: T) -> T {
    i = i.successor()
    return i
}

postfix func ++<T : _Incrementable>(inout i: T) -> T {
    let y = i
    i = i.successor()
    return y
}

// Decrement
prefix func --(inout x: Int) -> Int {
    x -= 1
    return x
}

postfix func --(inout x: Int) -> Int {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: UInt) -> UInt {
    x -= 1
    return x
}

postfix func --(inout x: UInt) -> UInt {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: Int8) -> Int8 {
    x -= 1
    return x
}

postfix func --(inout x: Int8) -> Int8 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: UInt8) -> UInt8 {
    x -= 1
    return x
}

postfix func --(inout x: UInt8) -> UInt8 {
    x -= 1
    return (x + 1)
}
prefix func --(inout x: Int16) -> Int16 {
    x -= 1
    return x
}

postfix func --(inout x: Int16) -> Int16 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: UInt16) -> UInt16 {
    x -= 1
    return x
}

postfix func --(inout x: UInt16) -> UInt16 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: Int32) -> Int32 {
    x -= 1
    return x
}

postfix func --(inout x: Int32) -> Int32 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: UInt32) -> UInt32 {
    x -= 1
    return x
}

postfix func --(inout x: UInt32) -> UInt32 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: Int64) -> Int64 {
    x -= 1
    return x
}

postfix func --(inout x: Int64) -> Int64 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: UInt64) -> UInt64 {
    x -= 1
    return x
}

postfix func --(inout x: UInt64) -> UInt64 {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: Double) -> Double {
    x -= 1
    return x
}

postfix func --(inout x: Double) -> Double {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: Float) -> Float {
    x -= 1
    return x
}

postfix func --(inout x: Float) -> Float {
    x -= 1
    return (x + 1)
}

prefix func --(inout x: Float80) -> Float80 {
    x -= 1
    return x
}

postfix func --(inout x: Float80) -> Float80 {
    x -= 1
    return (x + 1)
}

prefix func --<T : BidirectionalIndexType>(inout i: T) -> T {
    i = i.predecessor()
    return i
}

postfix func --<T : BidirectionalIndexType>(inout i: T) -> T {
    let y = i
    i = i.predecessor()
    return y
}
于 2016-04-27T17:09:13.173 回答
22

Apple 已经删除++了它,并使用另一种旧的传统方式使其变得更简单。

而不是++,您需要编写+=.

例子:

var x = 1

//Increment
x += 1 //Means x = x + 1 

同样对于递减运算符--,您需要编写-=

例子:

var x = 1

//Decrement
x -= 1 //Means x = x - 1

对于for循环:

增量示例:

代替

for var index = 0; index < 3; index ++ {
    print("index is \(index)")
}

你可以写:

//Example 1
for index in 0..<3 {
    print("index is \(index)")
}

//Example 2
for index in 0..<someArray.count {
    print("index is \(index)")
}

//Example 3
for index in 0...(someArray.count - 1) {
    print("index is \(index)")
}

减量示例:

for var index = 3; index >= 0; --index {
   print(index)
}

你可以写:

for index in 3.stride(to: 1, by: -1) {
   print(index)
}
//prints 3, 2

for index in 3.stride(through: 1, by: -1) {
   print(index)
}
//prints 3, 2, 1

for index in (0 ..< 3).reverse() {
   print(index)
}

for index in (0 ... 3).reverse() {
   print(index)
}

希望这可以帮助!

于 2016-04-06T01:59:51.620 回答
8

对于 Swift 4,您可以将++and--运算符恢复为Intand 其他类型的扩展。这是一个例子:

extension Int {
   @discardableResult
   static prefix func ++(x: inout Int) -> Int {
        x += 1
        return x
    }

    static postfix func ++(x: inout  Int) -> Int {
        defer {x += 1}
        return x
    }

    @discardableResult
    static prefix func --(x: inout Int) -> Int {
        x -= 1
        return x
    }

    static postfix func --(x: inout Int) -> Int {
        defer {x -= 1}
        return x
    }
}

它对其他类型的工作方式相同,例如UIInt, Int8, Float,Double等。

您可以将这些扩展粘贴到根目录中的单个文件中,并且它们可以在您那里的所有其他文件中使用。如果您在操场上查看它,它会完美运行。

于 2017-11-01T23:14:37.193 回答
7

Chris Lattner 与 ++ 和 -- 开战。他写道,“实际使用这些运算符的结果值的代码对于代码的读者/维护者来说往往是令人困惑和微妙的。他们鼓励“过于棘手”的代码,这些代码可能很可爱,但难以理解……虽然 Swift 有明确定义的评估顺序,但任何依赖它的代码(如 foo(++a, a++))都是不可取的,即使它是明确定义的……这些没有达到“如果我们还没有这些,我们会将它们添加到 Swift 3 中吗?”的度量标准</p>

Apple 希望保持 swift 是一种干净、清晰、不混淆且直截了当的语言。所以他们弃用了 ++ 和 -- 关键字。

于 2016-02-02T16:36:04.170 回答
6

警告截图

Xcode 给出了明确的Fix-it feature答案。

警告的解决方法

替换++ increment operator为老式value += 1(速记运算符)-- decrement operatorvalue -= 1

于 2016-07-18T05:47:31.980 回答
5

这是迄今为止发布的一些代码的通用版本。我会表达和其他人一样的担忧:最好不要在 Swift 中使用这些。我同意这可能会让那些将来阅读您的代码的人感到困惑。

prefix operator ++
prefix operator --
prefix func ++<T: Numeric> (_ val: inout T) -> T {
    val += 1
    return val
}

prefix func --<T: Numeric> (_ val: inout T) -> T {
    val -= 1
    return val
}

postfix operator ++
postfix operator --
postfix func ++<T: Numeric> (_ val: inout T) -> T {
    defer { val += 1 }
    return val
}

postfix func --<T: Numeric> (_ val: inout T) -> T {
    defer { val -= 1 }
    return val
}

这也可以写为 Numeric 类型的扩展。

于 2018-08-08T23:57:46.253 回答
4

文档

Swift 中的递增/递减运算符是在 Swift 开发的早期添加的,作为 C 的继承。这些是在没有太多考虑的情况下添加的,从那时起就没有考虑太多。本文档对它们进行了全新的审视,并最终建议我们将它们完全删除,因为它们令人困惑且无法承受。

于 2016-02-02T16:17:47.527 回答
0
var value : Int = 1

func theOldElegantWay() -> Int{
return value++
}

func theNewFashionWay() -> Int{
let temp = value
value += 1
return temp
}

这绝对是一个缺点,对吧?

于 2016-03-23T02:05:11.360 回答
0

在没有分号的语言中,它可能是模棱两可的。它是前缀还是后缀运算符?

考虑:

var x = y
++x

人类读取++x但解析器可以将其读取为y++.

于 2021-09-04T11:39:51.003 回答
0

由于您在 Swift 中从未真正使用过指针,因此在我看来删除++and运算符是有意义的。--但是,如果您不能没有,您可以将这些Swift 5+运算符声明添加到您的项目中:

@discardableResult
public prefix func ++<T: Numeric>(i: inout T) -> T {
    i += 1
    return i
}

@discardableResult
public postfix func ++<T: Numeric>(i: inout T) -> T {
    defer { i += 1 }
    return i
}

@discardableResult
public prefix func --<T: Numeric>(i: inout T) -> T {
    i -= 1
    return i
}

@discardableResult
public postfix func --<T: Numeric>(i: inout T) -> T {
    defer { i -= 1 }
    return i
}
于 2020-07-12T12:20:59.913 回答
-3

在 Swift 4.1 中可以这样实现:



    prefix operator ++
    postfix operator ++
    extension Int{
        static prefix func ++(x: inout Int)->Int{
            x += 1
            return x
        }
        static postfix func ++(x: inout Int)->Int{
            x += 1
            return x-1
        }
    }
    //example:
    var t = 5
    var s = t++
    print("\(t) \(s)")


请注意,尽管此解决方案与本文中的先前解决方案相似,但它们在 Swift 4.1 中不再有效,而本示例则有效。另请注意,上面提到 += 是 ++ 的替代品的任何人都没有完全理解运算符,因为 ++ 与赋值相结合实际上是两个操作,因此是一种快捷方式。在我的例子中:var s = t++做两件事:将 t 的值分配给 s,然后增加 t。如果 ++ 出现在前面,则相同的两个操作以相反的顺序完成。在我看来,Apple 关于为什么要删除此运算符的推理(在之前的答案中提到)不仅是错误的推理,而且我认为这是一个谎言,真正的原因是他们无法让编译器处理它。在以前的版本中给他们带来了麻烦,所以他们放弃了。“太复杂而无法理解运算符,因此被删除”的逻辑显然是一个谎言,因为 Swift 包含的运算符要复杂得多,用处也少得多,这些运算符没有被删除。此外,绝大多数编程语言都有它。JavaScript、C、C#、Java、C++ 等等。程序员乐于使用它。对谁来说太难理解这个运算符,

Swift 背后的策略很简单:Apple 认为程序员是愚蠢的,因此应该受到相应的对待。

事实是,2014 年 9 月推出的 Swift 现在应该在其他地方。其他语言发展得更快。

我可以列出该语言中的许多主要错误,从严重的错误:例如按值而不是按引用粘贴的数组,到令人讨厌的错误:可变参数函数不能接受数组,这是其背后的全部思想。我不认为 Apple 的员工甚至被允许查看 Java 等其他语言,所以他们甚至不知道 Apple 落后了很多年。苹果本可以采用 Java 作为一种语言,但如今,挑战不是技术,而是自我。如果他们打开 IntelliJ 来编写一些 Java,他们肯定会关闭他们的业务,因为他们明白,在这一点上,他们无法也永远不会赶上。

于 2018-04-26T07:47:29.623 回答