Rust 使用“let”绑定增加值的生存期

Rust 使用“let”绑定增加值的生存期,rust,lifetime,let,Rust,Lifetime,Let,我编写了以下代码以从stdin读取整数数组: use std::io::{self, BufRead}; fn main() { let stdin = io::stdin(); for line in stdin.lock().lines() { let xs: Vec<i32> = line.unwrap() .trim() .split(' ') .map(|s| s.pa

我编写了以下代码以从
stdin
读取整数数组:

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let xs: Vec<i32> = line.unwrap()
            .trim()
            .split(' ')
            .map(|s| s.parse().unwrap())
            .collect();

        println!("{:?}", xs);
    }
}
这没用!Rust回复了以下错误:

error[E0597]:借入值的有效期不够长
-->src/main.rs:6:18
|
6 |让ss=线。展开()。修剪()。拆分(“”);
|^^^^^^^^^^^^^^^^^-仍在借用时将临时值放在此处
|                  |
|临时值的寿命不够长
...
10 |     }
|-临时价值需要持续到此处
|
=注意:考虑使用“让”绑定来增加其生命周期。
这使我困惑。是
line
还是
ss
活得不够长?我如何使用
let
绑定来延长它们的寿命?我以为我已经在用
let


我把这本书通读了一遍,但还是不太明白。有人能给我一个提示吗?

这是关于
unwrap()
调用的,它正在获取包含的对象,但此引用应该比容器对象更有效,容器对象在下一行中超出了范围(它没有本地绑定)

如果您想获得更清晰的代码,一种非常常见的编写方法是:

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let xs: Vec<i32> = line.unwrap()
            .trim()
            .split(' ')
            .map(|s| s.parse().unwrap())
            .collect();

        println!("{:?}", xs);
    }
}
使用std::io:{self,BufRead};
fn main(){
设stdin=io::stdin();
对于stdin.lock().lines()中的行{
设xs:Vec=line.unwrap()
.trim()
.拆分(“”)
.map(| s | s.parse().unwrap())
.收集();
println!(“{:?}”,xs);
}
}

如果没有,您可以创建绑定到“unwrapped”结果并使用它。

在第二个版本中,
ss
的类型为。类型中的lifetime参数告诉我们对象包含引用。为了使赋值有效,引用必须指向该语句之后存在的对象。但是,使用
;换句话说,它将
Ok
变量的数据移出
Result
对象。因此,引用不会指向原始的
,而是指向临时对象

在第一个版本中,通过调用
map
,在长表达式的末尾使用临时表达式。要修复第二个版本,您需要绑定
unwrap()
的结果,以使该值保持足够长的有效期:

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let ss = line.trim().split(' ');
        let xs: Vec<i32> = ss.map(|s| s.parse().unwrap()).collect();

        println!("{:?}", xs);
    }
}
使用std::io:{self,BufRead};
fn main(){
设stdin=io::stdin();
对于stdin.lock().lines()中的行{
让line=line.unwrap();
设ss=line.trim().split(“”);
让xs:Vec=ss.map(| s | s.parse().unwrap()).collect();
println!(“{:?}”,xs);
}
}

那么你是说
超出了
let xs
行的范围,但不在
let ss
行,即使它们在同一块中?超出范围的是
行.unwrap()
结果。谢谢,我想我已经开始明白了。为了确保我正确理解你,
CharSplits
引用
行中的值。但实际上它引用了一个取自
Ok
的副本,该副本在
let ss
行结束时立即丢弃。而不仅仅是将所有值保持活动直到块结束?是的。临时值仅对生成该值的表达式所在的语句有效。请注意,此处有两个名为
line
的变量:第一个是
IoResult
(=
Result
),第二个是
String
unwrap()
字符串
移出
IoResult
,然后
IoResult
就不可用了(这也是我重复使用名称
:您无论如何都不能使用第一行
的原因)。
字符串
完全没有被复制。这很有趣。这样的动作是怎么做到的?是否复制了数据并销毁了原始数据?还是堆上的字符串和指向它的原始指针被破坏了?
String
结构包含一个
Vec
,其中包含指向数据(存储在堆上)的指针、长度和容量。发生移动时,会复制结构的成员,但不会复制引用的数据,也不会运行析构函数。然后,编译器会使原始副本不可用(如果您尝试使用该值,将出现错误),因此您不会访问所有权已转移的数据。
use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let ss = line.trim().split(' ');
        let xs: Vec<i32> = ss.map(|s| s.parse().unwrap()).collect();

        println!("{:?}", xs);
    }
}