Rust的一生 [英] Lifetimes in Rust

查看:77
本文介绍了Rust的一生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时我发现自己想编写可以通过以下两种方式之一调用的函数:

Occasionally I've found myself wanting to write functions that can be called in either of two ways:

// With a string literal:
let lines = read_file_lines("data.txt");

// With a string pointer:
let file_name = ~"data.txt";
let lines = read_file_lines(file_name);

我的第一个猜测是对参数类型使用借用的指针(&str),但是当这种方法不起作用时(它只允许我使用@str~str),我尝试了以下操作(通过复制Rust库),就可以了.

My first guess was to use a borrowed pointer (&str) for the parameter type, but when that didn't work (it only allowed me to use @str and ~str), I tried the following (by copying the Rust libraries), which did work.

fn read_file_lines<'a>(path: &'a str) -> ~[~str] {
    let read_result = file_reader(~Path(path));
    match read_result {
        Ok(file) => file.read_lines(),
        Err(e) => fail!(fmt!("Error reading file: %?", e))
    }
}

问题是我不明白自己在做什么.根据我的收集(主要是由于编译器错误),我声明了一个不受限制的生存期,并使用它来描述path参数(意味着可以将任何生存期都作为参数传递).

The problem is that I don't understand what I'm doing. From what I can gather (mostly from compiler errors), I'm declaring a lifetime on which there is no restriction, and using it to describe the path parameter (meaning that any lifetime can be passed as the parameter).

所以:

  • 我的理解模糊不清吗?
  • 什么是一生?我在哪里可以了解有关他们的更多信息?
  • 在上面的示例中,类型为&str的参数与类型为&'a str的参数有什么区别?
  • 当我在这里的时候,什么是'self?
  • Is my understanding vaguely accurate?
  • What is a lifetime? Where can I learn more about them?
  • What is the difference between a parameter of type &str and a parameter of type &'a str in the example above?
  • And while I'm at it, what is 'self?

(我正在使用Rust 0.7,如果对答案有所帮助的话)

(I'm using Rust 0.7, if it makes a difference to the answer)

推荐答案

更新2015-05-16 :原始问题中的代码适用于旧版本的Rust,但概念仍然存在相同的.此答案已更新为使用现代的Rust语法/库. (基本上将~[]更改为Vec,将~str更改为String,并在最后调整代码示例.)

Update 2015-05-16: the code in the original question applied to an old version of Rust, but the concepts remain the same. This answer has been updated to use modern Rust syntax/libraries. (Essentially changing ~[] to Vec and ~str to String and adjusting the code example at the end.)

我的理解模糊不清吗?
[...]
在上面的示例中,类型& str的参数与类型&'a str的参数有什么区别?

Is my understanding vaguely accurate?
[...]
What is the difference between a parameter of type &str and a parameter of type &'a str in the example above?

是的,这样的一生基本上说是没有限制".生命周期是一种将输出值与输入连接的方式,即fn foo<'a, T>(t: &'a T) -> &'a T表示foo返回的指针的寿命与t相同,也就是说,它指向的数据在与t(严格来说,至少要长这样).这基本上意味着返回值指向t指向的内存的某个子部分.

Yes, a lifetime like that says essentially "no restrictions", sort of. Lifetimes are a way to connect output values with inputs, i.e. fn foo<'a, T>(t: &'a T) -> &'a T says that foo returns a pointer that has the same lifetime as t, that is, the data it points to is valid for the same length of time as t (well, strictly, at least as long as). This basically implies that the return value points to some subsection of the memory that t points to.

所以,像fn<'a>(path: &'a str) -> Vec<String>这样的函数与编写{ let x = 1; return 2; }非常相似...这是一个未使用的变量.

So, a function like fn<'a>(path: &'a str) -> Vec<String> is very similar to writing { let x = 1; return 2; }... it's an unused variable.

Rust在写入&str时分配默认生存期,这完全等同于写入未使用变量的生存期.即fn(path: &str) -> Vec<String>'a的版本没有什么不同.只有在需要强制执行全局指针(例如特殊的'static生命周期)或者要返回引用(例如,-> &str)时,才可以使用生命周期,这仅与以下情况不同:返回值具有有效期(必须为一个或多个输入的有效期,或者为'static).

Rust assigns default lifetimes when writing &str, and this is exactly equivalent to writing the unused-variable lifetime. i.e. fn(path: &str) -> Vec<String> is no different to the version with 'as. The only time leaving off a lifetime is different to including it is if you need to enforce a global pointer (i.e. the special 'static lifetime), or if you want to return a reference (e.g. -> &str) which is only possible if the return value has a lifetime (and this must be either the lifetime of one-or-more of the inputs, or 'static).

什么是一生?我在哪里可以了解有关他们的更多信息?

What is a lifetime? Where can I learn more about them?

生存期是指指针所指向的数据保证存在多长时间,例如全局变量可以保证持续永远"(因此具有特殊的生存期'static).一种看待它们的巧妙方法是:生存期将数据连接到所有者所在的堆栈框架;一旦该堆栈帧退出,所有者将超出范围,并且指向该值/数据结构的任何指针均不再有效,并且生存期是编译器对此进行推理的一种方式. (在堆栈框架视图中,好像@具有与当前任务相关联的特殊堆栈框架,而static具有一个全局"堆栈框架).

A lifetime is how long the data a pointer points to is guaranteed to exist, e.g. a global variable is guarantee to last "forever" (so it's got the special lifetime 'static). One neat way to look at them is: lifetimes connect data to the stack frame on which their owner is placed; once that stack frame exits, the owner goes out of scope and any pointers to/into that value/data-structure are no longer valid, and the lifetime is a way for the compiler to reason about this. (With the stack frame view, it is as if @ has a special stack frame associated with the current task, and statics have a "global" stack frame).

还有该书的生存时间"一章

There's also a lifetimes chapter of the book, and this gist (NB. the code is now outdated but the concepts are still true) is a neat little demonstration of how one can use lifetimes to avoid having to copy/allocate (with a strong safety guarantee: no possibility of dangling pointers).

当我在这里的时候,什么是'self?

从字面上看没有什么特别的,只是某些地方要求类型具有生存期(例如,在struct/enum定义中和在impl中),并且当前只有'self'static是唯一接受的名称. 'static表示全局始终有效的指针,'self表示可以具有任何生存期的指针.调用(非static)生命周期(self以外的任何东西)是一个错误.

Literally nothing special, just certain places require types to have lifetimes (e.g. in struct/enum defintions and in impls), and currently 'self and 'static are the only accepted names. 'static for global always-valid pointers, 'self for something that can have any lifetime. It's a bug that calling that (non-static) lifetime anything other than self is an error.

总而言之,我会将该函数编写为:

All in all, I'd write that function like:

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;

fn read_file_lines(path: &Path) -> Vec<String> {
    match File::open(path) {
        Ok(file) => {
            let read = BufReader::new(file);
            read.lines().map(|x| x.unwrap()).collect()
        }
        Err(e) => panic!("Error reading file: {}", e)
    }
}

fn main() {
   let lines = read_file_lines(Path::new("foo/bar.txt"));
   // do things with lines
}

这篇关于Rust的一生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆