代码之家  ›  专栏  ›  技术社区  ›  John

var a=5和var a=int(5)有什么区别?

  •  -2
  • John  · 技术社区  · 5 年前

    声明变量时,文本值和整型文本值有什么不同吗?

    4 回复  |  直到 5 年前
        1
  •  4
  •   Rob Napier    5 年前

    在优化之前,是的,这些是不同的。 var a = 5 立即进行优化,以供将来参考 a 价值5。 var a = Int(5) 包括对的函数调用 SignedInteger.init . 您可以通过发出SIL来看到这一点:

    echo "var x = 5" | swiftc -emit-sil -
    
    // main
    sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
    bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
      alloc_global @$S4main1xSivp                     // id: %2
      %3 = global_addr @$S4main1xSivp : $*Int         // user: %6
      %4 = integer_literal $Builtin.Int64, 5          // user: %5
      %5 = struct $Int (%4 : $Builtin.Int64)          // user: %6
      store %5 to %3 : $*Int                          // id: %6
      %7 = integer_literal $Builtin.Int32, 0          // user: %8
      %8 = struct $Int32 (%7 : $Builtin.Int32)        // user: %9
      return %8 : $Int32                              // id: %9
    } // end sil function 'main'
    

    echo "var x = Int(5)" | swiftc -emit-sil -
    
    // main
    sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
    bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
      alloc_global @$S4main1xSivp                     // id: %2
      %3 = global_addr @$S4main1xSivp : $*Int         // user: %11
      %4 = metatype $@thin Int.Type
      %5 = metatype $@thick Int.Type                  // user: %11
      %6 = integer_literal $Builtin.Int64, 5          // user: %7
      %7 = struct $Int (%6 : $Builtin.Int64)          // user: %9
      %8 = alloc_stack $Int                           // users: %9, %12, %11
      store %7 to %8 : $*Int                          // id: %9
      // function_ref SignedInteger<>.init<A>(_:)
      %10 = function_ref @$SSZss17FixedWidthIntegerRzrlEyxqd__cSzRd__lufC : $@convention(method) <τ_0_0 where τ_0_0 : FixedWidthInteger, τ_0_0 : SignedInteger><τ_1_0 where τ_1_0 : BinaryInteger> (@in τ_1_0, @thick τ_0_0.Type) -> @out τ_0_0 // user: %11
      %11 = apply %10<Int, Int>(%3, %8, %5) : $@convention(method) <τ_0_0 where τ_0_0 : FixedWidthInteger, τ_0_0 : SignedInteger><τ_1_0 where τ_1_0 : BinaryInteger> (@in τ_1_0, @thick τ_0_0.Type) -> @out τ_0_0
      dealloc_stack %8 : $*Int                        // id: %12
      %13 = integer_literal $Builtin.Int32, 0         // user: %14
      %14 = struct $Int32 (%13 : $Builtin.Int32)      // user: %15
      return %14 : $Int32                             // id: %15
    } // end sil function 'main'
    

    然而,一旦它被优化(添加 -O swiftc 行),它们(基本上)与 var a=5 版本:

    // main
    sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
    bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
      alloc_global @$S4main1xSivp                     // id: %2
      %3 = global_addr @$S4main1xSivp : $*Int         // user: %6
      %4 = integer_literal $Builtin.Int64, 5          // user: %5
      %5 = struct $Int (%4 : $Builtin.Int64)          // user: %6
      store %5 to %3 : $*Int                          // id: %6
      %7 = integer_literal $Builtin.Int32, 0          // user: %8
      %8 = struct $Int32 (%7 : $Builtin.Int32)        // user: %9
      return %8 : $Int32                              // id: %9
    } // end sil function 'main'
    

    后者将为协议见证人发出大量额外的SIL,但这不会影响最终的二进制文件。

    您可以使用godbolt探索最终装配输出:

    正如您将要注意的,优化的版本完全相同。

    实际上,这并不重要。在swift中,省略类型是常见的样式,但在许多情况下需要省略类型,例如对于uint或int64类型,甚至int()有时对于清晰性也很有用。

    不管你写什么 var a: UInt = 5 var a = UInt(5) 只是风格,即使它们会导致稍微不同的未优化输出。请放心,优化器将很容易为您修复这些方法中的任何一种,并且只需以您的问题最清楚的方式编写。但当有疑问的时候,把它放在一边。这是斯威夫特的典型偏好。

        2
  •  6
  •   vacawama    5 年前
    var a = 5
    

    这创造了一个 Int 值为的变量 5 . 斯威夫特推断出 a 从整数文本。 int 当没有其他信息可用时,是整型文字的默认类型。

    var a = Int(5)
    

    这将调用初始值设定项 int 用一个 int 价值 就像上面的值一样。

    若要了解有关此初始值设定项的详细信息,请将语句更改为:

    var a = Int.init(5)
    

    然后 选项 点击 init .

    你会看到:

    总结

    从给定的整数创建新实例。

    宣言

    convenience init<T>(_ source: T) where T : BinaryInteger

    讨论

    使用此初始值设定项可在 知道该值在该类型的范围内。传递一个值 不能用这种类型表示会导致运行时错误。

    因此,您不必要地为调用初始值设定项 int 其值已被推断为 int . 正如@robnapier在他的 excellent answer ,优化器将清除多余的调用。但我想,为什么要麻烦呢?

    如果要注意类型,可以显式键入变量:

    var a: Int = 5
    

    但让斯威夫特推断出这一类型:

    var a=5
    

    是最好的方法。

        3
  •  3
  •   jtouzy    5 年前
    let a = 5
    print(a)            // 5
    print(type(of: a))  // Int
    let b = Int(5)
    print(b)            // 5
    print(type(of: b))  // Int
    

    只需使用int类构造函数。在你的第二种方式中,它是含蓄的。选择你的第一个选项。

        4
  •  2
  •   Dávid Pásztor    5 年前

    swift使用类型推理,并推断整型文本类型 Int ,所以 a 在里面 let a = 5 int . 因此,将一个整型文字传递给 int 没有其他效果,因此您的两个示例获得相同的结果。