Время жизни ссылки

Аннотации и время жизни ссылки

Последнее обновление: 25.04.2021

Каждая ссылка в Rust имеет свое время жизни, которое обычно задается областью видимости или контекстом, в рамках которого ссылку можно использовать. И большинстве случаев Rust сам выводит для ссылки время жизни, опять же исходя из ее области видимости. Рассмотрим простейший пример:

fn main(){
	let x;
	
	{
		let n = 2;
		x = &n;
	} // конец области видимости переменной n и ссылки &n
	
	println!("x: {}", x);
}

Здесь во внутреннем блоке кода переменная x получает ссылку на данные переменной n: x = &n;

При завершении внутреннего блока кода память под переменную n освобождается, соответственно ссылка &n становится недействительной, а переменная x теперь ссылается на несуществующие данные. Однако чуть ниже идет попытка обратиться к данным переменной x, которые уже являются недействительными:

println!("x: {}", x);

К счастью компилятор Rust умееет отслеживать подробные ситуации, поэтому при компиляции мы получим ошибку:

reference does not live long enough в Rust

Если бы обе переменные были определены в одной области видимости, то такой проблемы не возникло:

fn main(){
	let x;
	let n = 2;
	x = &n;
	println!("x: {}", x);	// x: 2
}

Либо, если бы переменной x только применялась в той области видимости, в которой действительно ее значение:

fn main(){
	let x;
	{
		let n = 2;
		x = &n;
		println!("x: {}", x);	// x: 2
	}
}

Хотя в большинстве случаев Rust сам может вывести время жизни ссылки, в некоторых случаях это время необходимо указывать явным образом. Так, рассмотрим другой пример - функцию, которая возвращает строковый слайс &str:

fn main(){
	let message = get_message();
	println!("message: {}", message);
}

fn get_message() -> &str {
	"hello"
}

Здесь функция get_message() возвращает объект &str. Однако Rust не может определить время жизни данной ссылки, поэтому при компиляции будет сгенерирована ошибка missing lifetime specifier:

missing lifetime specifier в Rust

И в данной ситуации нам необходимо указать явным образом время жизни для возвращаемой ссылки.

Установка времени жизни ссылки

Для установки времени жизни ссылки применяются аннотации, которые должны начинаться с апострофа ', например, аннотация 'a.

Аннотация помещается после символа амперсанда &, но до определения типа данных:

&i32        // обычная ссылка
&'a i32     // ссылка с указанным временем жизни
&'a mut i32 // изменяемая ссылка с указанным временем жизни

Так, изменим предыдущий пример, применив аннотации времени жизни:

fn main(){
	let message = get_message();
	println!("message: {}", message);
}

fn get_message<'a>() -> &'a str {
	"hello"
}

После названия функции необходимо указать названи аннотации. В данном случае аннотация называется 'a.

fn get_message<'a>()

Далее аннотация применяется к возвращаемому результату:

-> &'a str 

Теперь программа будет успешно компилироваться и запускаться.

Стоит учесть, что аннотации времени жизни сами по себе они не имеют большого значения. В реальности они не меняют время жизни ссылки. Их назначение - указать компилятору, как аннотации времени жизни соотносятся друг с другом. То есть не существует в языке Rust некой встроенной аннотации 'a - это название мы даем аннотации сами.

Однако какое же время жизни будет у результата, который возвращается данной функцией? Если время жизни возвращаемой ссылки НЕ привязано к времени жизни параметров функции, то тогда время жизни возвращаемой ссылки соответствует времени жизни возвращаемого значения.

В данном случае в функции параметров нет, а возвращаемое значение - строковый литерал "hello". Строковые литералы сохраняются в памяти в течение всей работы программы, поэтому время жизни подобной ссылки - все время работы программы.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850