Мы уже знаем, что при передаче владения по ссылке, всегда происходит контроль ее
времени жизни (lifetime). Время жизни ссылки зависит от времени жизни ресурса (область памяти, в которой хранятся данные).
Время жизни ссылки не может быть больше, чем время жизни данных, на которые она ссылается. Время жизни данных начинается в точке размещения их в памяти (объявление и инициализация переменной) и заканчивается при выходе из блока видимости (очистка памяти). Время жизни ссылки начинается в точке ее объявления и инициализации и заканчивается при выходе из блока видимости. Главное правило – ссылка не может появиться раньше, чем данные, на которые ссылается и существовать после уничтожения данных, на которые ссылается.

В простом случае компилятор легко находит ошибки, но при работе со структурами данных, их методами или функциями, это сделать значительно труднее, т.к. не возможно однозначно определить время жизни ссылок, их составляющих, на этапе компиляции. Например, у нас есть структура, в которой есть поле - ссылка. Для правильной работы требуется, чтобы время жизни ссылки на такую структуру не превышало времени жизни ссылки, содержащейся в ней. В этих случаях потребуется участие программиста. Для того чтобы определить это участие, на уровне языка введен инструмент позволяющий определить отношение между временем жизни. Про инструмент мы говорили в статье
Владение ресурсами в Rust. Часть 4. Для того чтобы облегчить это определение для работы с функциями, компилятор использует специальные
правила (Lifetime Elision) для самостоятельного определения времени жизни в наиболее распространенных случаях, про них мы поговорим сегодня более подробно. Этих правил три,
первое направлено на входные параметры функции, остальные два на возвращаемое значение.
Первое правило – Если параметры для функции содержат несколько ссылок, то для каждой из них определяется отдельное время жизни.
Второе правило – Возвращаемой ссылке присваивается время жизни единственной ссылки в параметрах.
Третье правило – Возвращаемой ссылке присваивается время жизни self-ссылки из нескольких ссылок в параметрах.
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Point {
pub fn new(x: i32, y: i32) -> Self {
Point {
x,
y,
}
}
}
#[derive(Debug)]
struct Line<'a> {
start: &'a Point,
end: &'a Point,
}
impl<'a> Line<'a> {
//Custom lifetime
pub fn new(start: &'a Point, end: &'a Point) -> Self {
Line {
start,
end,
}
}
}
#[derive(Debug)]
struct PolyLine<'a> {
points: Vec<&'a Point>,
}
impl<'a> PolyLine<'a> {
pub fn new() -> Self {
PolyLine {
points: Vec::new()
}
}
//Rule #1
pub fn add_point(&mut self, point: &'a Point) {
self.points.push(point);
}
//Rule #3
pub fn get_point_by_indx(&self, _p: &Point, indx: usize) -> &Point {
self.points.get(indx).unwrap()
}
//Rule #2
pub fn via(p: &Point) -> &Point {
p
}
}
fn main() {
let point_1 = Point::new(0, 0);
let point_2 = Point::new(5, 5);
let line_1 = Line::new(&point_1, &point_2);
let line_2 = Line::new(&point_2, &point_1);
println!("{:?},\n{:?};", line_1, line_2);
let mut poly_line_1 = PolyLine::new();
poly_line_1.add_point(PolyLine::via(&point_1));
poly_line_1.add_point(&point_2);
println!("{:?}", poly_line_1);
println!("{:?}", poly_line_1.get_point_by_indx(&point_1,1));
}
Перегуд В.
Комментариев нет:
Отправить комментарий