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);
}
}