guard & defer

本文深入探讨Swift2.0新增的控制流表达式guard和defer。guard用于条件判断,提前返回错误,提高代码可读性;defer则确保在代码块退出时执行特定操作,有效管理资源释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Swift 2.0 带来了两个新的能够简化程序和提高效率的控制流表达形式:guard 和 defer。前者可以让代码编写更流畅,后者能够让执行推迟。

guard

guard 是一个要求表达式的值为 true 从而继续执行的条件语句。如果表达式为 false,则会执行必须提供的 else 分支。

func sayHello(numberOfTimes: Int) {
    guard numberOfTimes > 0 else {
        return
    }
}

使用 guard 来避免过多的缩进和错误

使用if可能在大段代码之后才写到异常情况,而使用guard每一个错误都在相应的检查之后立刻被抛出(尽早返回错误),使代码可读性更高。

不要在 guard 中双重否定

不要滥用这个新的流程控制机制——特别是在条件表达式已经表示否定的情况下。

举个例子,如果你想要在一个字符串为空是提早退出,不要这样写:

guard !string.isEmpty else {
    return
}

defer

Swift 鼓励用尽早返回错误来代替嵌套 if 的处理方式。尽早返回让处理更清晰了,但是已经被初始化(可能也正在被使用)的资源必须在返回前被处理干净。

defer 关键字为此提供了安全又简单的处理方式:声明一个 block,当前代码执行的闭包退出时会执行该 block。

经常 defer

如果在同一个作用域内使用多个 defer 语句,它们会根据出现顺序反过来执行——像栈一样。这个反序是非常重要的细节,保证了被延迟的代码块创建时作用域内存在的东西,在代码块执行同样存在。

    func test(){
        defer {
            print(3)
        }
        
        defer {
            defer {
                print(2)
            }
            print(1)
        }
        
        defer {
            print(4)
        }
    }

打印结果:4
1
2
3
注:嵌套defer先执行外层,后执行内层。

正确 defer

如果在 defer 语句中引用了一个变量,执行时会用到变量最终的值。换句话说:defer 代码块不会捕获变量当前的值。

仔细 defer

另一件需要注意的事情,那就是 defer 代码块无法跳出它所在的作用域。因此如你尝试调用一个会 throw 的方法,抛出的错误就无法传递到其周围的上下文。

func burnAfterReading(file url: URL) throws {
    defer { try FileManager.default.removeItem(at: url) }
    // ? Errors not handled

    let string = try String(contentsOf: url)
}

作为替代,你可以使用 try? 来无视掉错误,或者直接将语句移出 defer 代码块,将其放到函数的最后,正常的执行。

### C++ `defer_lock` 机制解析 #### 基本概念 `std::defer_lock` 是一种特殊的锁定策略,当将其作为参数传递给 `std::unique_lock` 或者 `std::lock_guard` 时,不会立即尝试获取互斥锁。相反,这允许稍后通过显式的调用来控制何时实际锁定互斥量[^4]。 #### 实际应用案例 考虑一个多线程环境中需要按顺序获得多个互斥锁的情况,为了避免死锁的发生,可以利用延迟加载特性来协调这些锁之间的关系。下面是一个简单的例子展示如何使用 `defer_lock` 来管理三个不同的互斥对象: ```cpp #include <iostream> #include <mutex> void manage_multiple_mutexes(){ std::mutex m1; std::mutex m2; std::mutex m3; // 创建未上锁的状态下的 unique_locks std::unique_lock<std::mutex> ul1{m1,std::defer_lock}; std::unique_lock<std::mutex> ul2{m2,std::defer_lock}; std::unique_lock<std::mutex> ul3{m3,std::defer_lock}; // 同时对这三个 mutex 加锁而不用担心死锁问题 std::lock(ul1, ul2, ul3); // 此处执行受保护的操作... // 当离开作用域时,所有的 locks 都会被自动释放 } ``` 上述代码展示了如何安全地处理多个互斥资源而不引发潜在的死锁风险。这里的关键在于 `std::lock()` 函数能够一次性成功或者失败地占有所有指定的互斥变量;如果任何一个无法被立刻占用,则整个过程都不会发生任何改变[^2]。 #### 主要优势 采用这种方式的主要好处是可以更灵活地管理同步复杂的并发场景,在某些情况下还可以提高性能并减少竞争条件的可能性。此外,由于 `std::unique_lock` 支持动态绑定到不同的互斥类型以及提供更多的灵活性(比如支持超时等待),因此非常适合那些需要精细调整的行为模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值