< 返回版块

林深好材 发表于 2024-12-04 15:40

Tags:生命周期

rust1.82 为什么能编译代码片段A,而不能编译代码片段B

代码片段A

let config= match config_option {
            None => &Config::default(),
            Some(config) => config,
        };

代码片段B

let config = config_option.unwrap_or_else(|| &Config::default());

评论区

写评论
作者 林深好材 2024-12-05 14:39

感谢如此详细的回复。

--
👇
LazyQc: 首先,片段B在任何类似语言里都不应该是被认为有效可行的,因为它返回了一个函数(闭包)内的本地变量的引用,在函数返回后其变量就会被销毁,所以rust会阻止这种写法,这应该属于引用/指针的最基础规定了。

其次,片段A属于rust对表达式的一种友好支持(即extending based on expression,看上一个评论) 通俗的讲&Config::default()可以分成两步:Config::default()创建一个匿名变量(不能显式可见,但栈上会如变量一般分配位置),再返回其引用,rust规定了其有效作用域跟随其接收的变量,即这里绑定了config变量生命周期,在该生命周期失效后,原“匿名变量”才会被销毁。

// 实际不存在这个变量,因为它仅仅是存在于当前栈(占位),但任何地方都不可见,只能在None分支通过config访问
let _anonymous_var;
let config = match config_option {
    None => {
        _anonymous_var = Config::default();
        &_anonymous_var
    },
    Some(config) => config,
};
作者 林深好材 2024-12-05 14:17

书写错误。由于不知道怎么表示修改痕迹,因此直接修订成最后结果了

--
👇
Joe-Alwyn:

代码A是&Config::default(),代码B是&ConsoleLoggingConfig::default(),类型不一样

LazyQc 2024-12-05 11:03

首先,片段B在任何类似语言里都不应该是被认为有效可行的,因为它返回了一个函数(闭包)内的本地变量的引用,在函数返回后其变量就会被销毁,所以rust会阻止这种写法,这应该属于引用/指针的最基础规定了。

其次,片段A属于rust对表达式的一种友好支持(即extending based on expression,看上一个评论) 通俗的讲&Config::default()可以分成两步:Config::default()创建一个匿名变量(不能显式可见,但栈上会如变量一般分配位置),再返回其引用,rust规定了其有效作用域跟随其接收的变量,即这里绑定了config变量生命周期,在该生命周期失效后,原“匿名变量”才会被销毁。

// 实际不存在这个变量,因为它仅仅是存在于当前栈(占位),但任何地方都不可见,只能在None分支通过config访问
let _anonymous_var;
let config = match config_option {
    None => {
        _anonymous_var = Config::default();
        &_anonymous_var
    },
    Some(config) => config,
};
QingyaoLin 2024-12-04 22:02

extending-based-on-expressions

&temp() // success
Some(&temp()) // error
```rust
Bai-Jinlin 2024-12-04 16:03

临时变量生命周期的问题,我的理解是,第一个case中,你match创建的临时变量走的临时变量的特殊规则,可以提升其生命周期保证引用的有效。

第二次case就是普通的一个函数返回内部创建变量的引用的规则,这是肯定不可能正确的。

Joe-Alwyn 2024-12-04 15:53

代码A是&Config::default(),代码B是&ConsoleLoggingConfig::default(),类型不一样

1 共 6 条评论, 1 页