rust 不带分号的return表达式的性能是否优于使用return;在拉斯特吗

sdnqo3pr  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(169)

我通常在函数的末尾使用return foo;,因为我觉得这样更容易理解。但是我不确定这是否是个好主意,因为"正常"的返回表达式是没有分号的。我应该使用没有分号的返回表达式吗(例如为了更好的性能)?
示例:

//My typical functions
pub fn user_exist(&self, key: &str) -> Result<(), ApiError> {
    let mut cache: PooledConnection<Client> = connection()?;

    cache.exists(key)?;
    return Ok(());
}

// Is it better to use this?
pub fn user_exist(&self, key: &str) -> Result<(), ApiError> {
    let mut cache: PooledConnection<Client> = connection()?;

    cache.exists(key)?;
    Ok(())
}
hm2xizp9

hm2xizp91#

编译器并不区分这两者,它们是完全等价的。考虑下面两个例子:

pub fn square1(x: usize) -> usize {
    x*x
}

pub fn square2(x: usize) -> usize {
    return x*x;
}

Looking at the assembly在godbolt编译器资源管理器中,我们得到相同的代码:

example::square1:
        mov     rax, rdi
        imul    rax, rdi
        ret

example::square2:
        mov     rax, rdi
        imul    rax, rdi
        ret

从样式的Angular 来看,除非提前返回,否则不使用return语句是惯例,更多细节请参见this question
edit:@Chayim Friedman提出了一个很好的观点,即查看程序集并不能证明它们是等价的。尽管同样也不是很难证明,但这两个函数的looking at the MIR提供了进一步的证据,证明编译器对这两个返回值的处理是相同的:

fn square1(_1: usize) -> usize {
    debug x => _1;                       // in scope 0 at src/lib.rs:1:16: 1:17
    let mut _0: usize;                   // return place in scope 0 at src/lib.rs:1:29: 1:34
    let mut _2: usize;                   // in scope 0 at src/lib.rs:2:5: 2:6
    let mut _3: usize;                   // in scope 0 at src/lib.rs:2:7: 2:8
    let mut _4: (usize, bool);           // in scope 0 at src/lib.rs:2:5: 2:8

    bb0: {
        _2 = _1;                         // scope 0 at src/lib.rs:2:5: 2:6
        _3 = _1;                         // scope 0 at src/lib.rs:2:7: 2:8
        _4 = CheckedMul(_2, _3);         // scope 0 at src/lib.rs:2:5: 2:8
        assert(!move (_4.1: bool), "attempt to compute `{} * {}`, which would overflow", move _2, move _3) -> bb1; // scope 0 at src/lib.rs:2:5: 2:8
    }

    bb1: {
        _0 = move (_4.0: usize);         // scope 0 at src/lib.rs:2:5: 2:8
        return;                          // scope 0 at src/lib.rs:3:2: 3:2
    }
}

fn square2(_1: usize) -> usize {
    debug x => _1;                       // in scope 0 at src/lib.rs:5:16: 5:17
    let mut _0: usize;                   // return place in scope 0 at src/lib.rs:5:29: 5:34
    let mut _2: usize;                   // in scope 0 at src/lib.rs:6:12: 6:13
    let mut _3: usize;                   // in scope 0 at src/lib.rs:6:14: 6:15
    let mut _4: (usize, bool);           // in scope 0 at src/lib.rs:6:12: 6:15

    bb0: {
        _2 = _1;                         // scope 0 at src/lib.rs:6:12: 6:13
        _3 = _1;                         // scope 0 at src/lib.rs:6:14: 6:15
        _4 = CheckedMul(_2, _3);         // scope 0 at src/lib.rs:6:12: 6:15
        assert(!move (_4.1: bool), "attempt to compute `{} * {}`, which would overflow", move _2, move _3) -> bb1; // scope 0 at src/lib.rs:6:12: 6:15
    }

    bb1: {
        _0 = move (_4.0: usize);         // scope 0 at src/lib.rs:6:12: 6:15
        return;                          // scope 0 at src/lib.rs:7:2: 7:2
    }
}

相关问题