2014-11-09 101 views
1

我得到一个警告,will never be executed用下面的代码条件运算符警告

代码:

func f1() 
{ 
    var a1 : Int = 100 

    a1 = 1 

    var a2 = (a1 > 40 ? 1 : 0) //No warning 

    var a3 = (a1 > 40 ? "aaa" : "bbb") //Warning - will never be executed (points to "aaa") 
} 

问题:

  • 我知道基于上述逻辑,a3将得到值"bbb"但应该有一个 警告?
  • 为什么没有评估值的警告a2
  • 编译器如何评估这个值?我认为这些值将在运行时确定。 (注意的a1值分配后变更)
+0

我在操场上没有收到任何警告。 – Shuo 2014-11-09 05:05:01

+0

我创建了一个OS X命令行工具项目,我得到了这个警告 – user1046037 2014-11-09 05:06:44

+0

我也没有在命令行工具中得到警告。你使用的是什么版本的Xcode,这是main.swift文件中唯一的代码? – drewag 2014-11-09 05:09:16

回答

2
var a3 = (a1 > 40 ? "aaa" : "bbb") //Warning 

之所以存在就行了警告,因为它实际上调用一些代码。它通过调用String的init()构造一个String实例。

a1 > 40 ? 1 : 0 

这没有任何警告,因为它是原始值,这不涉及任何的init()或实例创建等

事情变得有趣..

func f1() 
    { 
     struct F { 
      init(x: Int){ 
      } 
     } 

     var a1 : Int = 100 

     a1 = 1 

     var a2 = (a1 > 40 ? Int(1) : Int(0))  // No Warning 

     var a4 = (a1 > 40 ? Int(Int(1) + UInt8(2)) : Int(0)) // Warning 

     var a3 = (a1 > 40 ? String("aaa") : "bbb") // Warning 

     var a5: F = (a1 > 40 ? F(x: a2) : F(x: a1)) // Warning 
    } 

为什么A3和a5有警告,可以解释。但为什么a2没有警告,它调用Int(1),它应该调用struct Int的init()。原因是“编译器优化”。 a4有警告,表明swift编译器的优化是相对浅的。 :)

编辑

从生成的代码,你可以看到不同之处。对于简单的Int(0),struct的init没有被调用。

var a = Int(0) 

    0x1006946d0: pushq %rbp 
    0x1006946d1: movq %rsp, %rbp 
    0x1006946d4: subq $0x20, %rsp 
    0x1006946d8: movq %rdi, -0x10(%rbp) 
    0x1006946dc: movq %rdi, -0x18(%rbp) 
-> 0x1006946e0: movq $0x0, -0x8(%rbp) 
    0x1006946e8: callq 0x1006b0f14    ; symbol stub for: objc_release 
    0x1006946ed: addq $0x20, %rsp 
    0x1006946f1: popq %rbp 
    0x1006946f2: retq 

    var a2 = Int(Int(0x0) + UInt8(0xE)) 

    0x1007175f0: addq $0x8, %rax 
    0x1007175f6: movq 0x1ebc3(%rip), %r8  ; (void *)0x0000000104a89d88: protocol witness table for Swift.UInt8 : Swift.Strideable 
    0x1007175fd: movq 0x1eaac(%rip), %rcx  ; (void *)0x0000000104a92f80: direct type metadata for Swift.Int 
    0x100717604: addq $0x8, %rcx 
    0x10071760b: movq 0x1eb5e(%rip), %rdx  ; (void *)0x0000000104a8b228: protocol witness table for Swift.Int : Swift.SignedNumberType 
    0x100717612: movq 0x1eb67(%rip), %rsi  ; (void *)0x0000000104a8b0c8: protocol witness table for Swift.Int : Swift._BuiltinIntegerLiteralConvertible 
    0x100717619: leaq -0x38(%rbp), %r9 
    0x10071761d: leaq -0x30(%rbp), %r10 
    0x100717621: leaq -0x28(%rbp), %r11 
    0x100717625: movq %rdi, -0x18(%rbp) 
    0x100717629: movq %rdi, -0x20(%rbp) 
-> 0x10071762d: movq $0xb, -0x28(%rbp) 
    0x100717635: movb $0xe, -0x30(%rbp) 
    0x100717639: movq %rdi, -0x40(%rbp) 
    0x10071763d: movq %r9, %rdi 
    0x100717640: movq %rsi, -0x48(%rbp) 
    0x100717644: movq %r11, %rsi 
    0x100717647: movq %rdx, -0x50(%rbp) 
+0

Int和String都是Swift中的struct。尝试下面的代码:'var a2 =(a1> 40?Int(1):Int(0))//没有警告'因此,都调用初始化/构造函数,但没有警告为Int,而出现警告字符串 – user1046037 2014-11-09 05:53:53

+0

a2和a3类似,但没有a2的警告,并且a3有警告。两者都使用构造函数/初始化程序。而a4有一个警告......使它更有趣(令人困惑) – user1046037 2014-11-09 05:59:36

+0

@ user1046037这是编译器优化的地方。Swift编译器试图生成高性能代码,因此它删除了Int()的init。如果感兴趣,您可以阅读生成的程序集。 – Shuo 2014-11-09 06:03:47