当前位置: 首页 > 知识库问答 >
问题:

为什么Swift语言指南建议使用Int“即使已知值是非负的”?

濮彬
2023-03-14

这是一个关于Swift编程风格的问题,特别是IntvsUInt

Swift编程语言指南建议程序员使用通用的有符号整数类型Int,即使已知变量为非负。从指南中:

仅当您特别需要大小与平台本机字大小相同的无符号整数类型时,才使用UInt。如果不是这种情况,则Int是优选的,即使当要存储的值已知是非负的。对整数值一致使用Int有助于代码互操作性,避免了在不同数字类型之间转换的需要,并匹配整数类型推断,如类型安全和类型推断中所述。

但是,UInt在32位体系结构上是32位无符号的,在64位体系结构上是64位无符号的,因此在UInt上使用Int对性能没有好处。

相比之下,Swift指南给出了一个后面的例子:

让年龄=-3
断言(年龄

在这里,如果代码编写为:

let age:UInt = -3  
// this causes a compiler error because -3 is negative

在许多其他情况下(例如,对集合进行索引的任何内容),使用UInt将在编译时而不是运行时捕获问题。

所以问题是:Swift编程语言指南中的建议是否合理,使用Int“即使已知要存储的值为非负”的好处是否超过了使用UInt的安全好处?

附加说明:使用Swift几周后,现在很明显需要与CocoaUInt的互操作性。例如,AVFoundation框架在任何需要计数的地方使用无符号整数(样本/帧/通道数等)。将这些值转换为Int可能会导致值大于Int.max的严重错误。

共有2个答案

魏鸿哲
2023-03-14

你的问题里说..."对整数值一致使用Int有助于代码互操作性,避免了在不同数字类型之间转换的需要,并匹配整数类型推断,如类型安全和类型推断中所述。"

这避免了将Int分配给UInt等问题。分配给UInts的负值会导致较大的值,而不是预期的负值。两者的二进制表示不能区分一种类型和另一种类型。

此外,两者都是类,一个不是另一个的后代。构建的类接收Ints不能在不重载的情况下接收UInts,这意味着当大多数框架接收Ints时,在两者之间进行转换将是UInts的一项常见任务。两者之间的转换也可以成为一项非同寻常的任务。

前面两段提到“互操作性”和“不同数字类型之间的转换”。如果不使用UINT可以避免的问题。

宋康安
2023-03-14

我认为使用UInt并不像你想象的那样安全。正如你所指出的:

let age:UInt = -3

导致编译器错误。我还尝试:

let myAge:Int = 1
let age:UInt = UInt(myAge) - 3

这也导致了一个编译器错误。然而,以下(我认为在实际程序中更常见)场景没有编译器错误,但实际上导致了EXC\u BAD\u指令的运行时错误

func sub10(num: Int) -> UInt {
    return UInt(num - 10) //Runtime error when num < 10
}
sub10(4)

以及:

class A {
    var aboveZero:UInt
    init() { aboveZero = 1 }
}
let a = A()
a.aboveZero = a.aboveZero - 10 //Runtime error

如果这些是普通的Int,而不是崩溃,您可以添加代码来检查您的条件:

if a.aboveZero > 0 {
    //Do your thing
} else {
    //Handle bad data
}

我甚至可能会将他们反对使用UInts的建议等同于他们反对使用隐式展开选项的建议:除非你确定不会有任何负面影响,否则不要这样做,否则你会出现运行时错误(最简单的情况除外)。

 类似资料:
  • 问题内容: 在Swift 2.2中阅读Darwin库时,我发现了以下代码。 第二行中的“ @_silgen_name”是什么? 我从这里找到了以下信息,但是我想要更多详细信息,例如Apple Developer Library。 如果只是要从C调用的一组特定的Swift函数,则可以使用@_silgen_name属性覆盖改写的名称,和/或使它们成为@convention(c)以使用C调用约定。 问题

  • 问题内容: 我最近一直在使用Hibernate 3.5和Spring 3进行一些工作,但是我对Hibernate还是比较陌生,并认为Spring中的类使将Hibernate与我的域类一起使用变得容易且容易。 但是,在搜索一个不相关的问题时,我看到有人提到,这不是使用Spring和Hibernate的最佳方法。任何人都可以阐明以下几点: 为什么不推荐? 整合Hibernate和Spring的最佳方法

  • 问题内容: 因此,我来​​自C语言背景(最初,尽管我已经有近5年没有使用该语言了,但我仍在尝试),并试图从Java字符串中解析一些值。在CI中将使用sscanf。在Java中,人们告诉我“使用Scanner或StringTokenizer”,但是我看不到如何使用它们来实现我的目的。 我的输入字符串看起来像“ 17-MAR-11 15.52.25.000000000”。在CI中将执行以下操作: 但是

  • 问题内容: Java文档似乎并未提及有关的弃用的任何内容,但我一直很早就听说过它的弃用情况。是因为它具有错误/错误而被弃用,还是整体上更好使用? 我有一些使用的代码,我想知道我是否应该认真考虑将其重构为使用,还是弃用纯粹是为了方便而我的代码是安全的。 问题答案: 从javadoc中获取StringTokenizer: 是旧类,出于兼容性原因保留,尽管在新代码中不鼓励使用它。建议任何寻求此功能的人改

  • 问题内容: 我找不到任何解释为什么Apache Lang3 v3.7中不推荐使用StringEscapeUtils。 https://commons.apache.org/proper/commons- lang/apidocs/org/apache/commons/lang3/StringEscapeUtils.html 我们现在应该使用什么来进行HTML转义/转义 问题答案: 班级已从包裹中移

  • 问题内容: 为什么不推荐使用? 问题答案: 在javadoc中说为什么。被设计为低负载并发的一种简单解决方案,但它甚至无法解决: 请注意,SingleThreadModel不能解决所有线程安全问题。例如,即使使用SingleThreadModel servlet,会话属性和静态变量仍然可以同时由多个线程上的多个请求访问。建议开发人员采取其他方法解决这些问题,而不要实现此接口,例如,避免使用实例变量

  • 问题内容: 也许有人可以帮助我理解,因为我觉得我缺少一些可能会影响程序运行方式的东西。 我正在使用ByteArrayOutputStream。除非我错过了很多东西,否则此类的重点是创建一个byte []数组以供其他用途。 但是,BAOS上的“普通”写入功能采用的是整数而不是字节(ByteArrayOutputStream.write)。 根据此(原始数据类型)页面,在Java中,int是32位数据

  • 本文向大家介绍Swift语言类专用协议,包括了Swift语言类专用协议的使用技巧和注意事项,需要的朋友参考一下 示例 协议可以指定只有一个类可以通过使用class其继承列表中的关键字来实现它。此关键字必须出现在此列表中任何其他继承的协议之前。 如果非类类型尝试实现ClassOnlyProtocol,则会生成编译器错误。 其他协议可能继承自ClassOnlyProtocol,但它们具有相同的仅类要求