История изменений
Исправление
vertexua,
(текущая версия)
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.
Лайфтаймы еще помогают в сигнатурах функций
fn process(a &str, b: &str) -> &str {
...
}
Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a
, b
или их подстроки. Но какие?
fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}
Все, расходимся, это кусок a
.
Это важно в лапше вроде такой
let a = String::new("a");
let b = String::new("b");
let result = process(&a, &b);
// Тут мы вроде бы вернули a, b, но секретно ссылаемся на a внутри result.
i_eat_variables(a); // Ошибка компиляции. Тут единолично хотят украсть владение над a, переместить ее
i_eat_variables(b); // Кстати вот тут ошибки не было бы.
println("{}", result);
Исправление
vertexua,
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.
Лайфтаймы еще помогают в сигнатурах функций
fn process(a &str, b: &str) -> &str {
...
}
Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a
, b
или их подстроки. Но какие?
fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}
Все, расходимся, это кусок a
.
Это важно в лапше вроде такой
let a = String::new("a");
let b = String::new("b");
let result = process(&a, &b);
// Тут мы вроде бы вернули a, b, но секретно ссылаемся на a внутри result.
i_eat_variables(a); // Ошибка компиляции.
i_eat_variables(b); // Кстати вот тут ошибки не было бы.
Исправление
vertexua,
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.
Лайфтаймы еще помогают в сигнатурах функций
fn process(a &str, b: &str) -> &str {
...
}
Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a
, b
или их подстроки. Но какие?
fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}
Все, расходимся, это кусок a
.
Исправление
vertexua,
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.
Лайфтаймы еще помогают в сигнатурах функций
fn process(a &str, b: &str) -> &str {
...
}
Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a
, b
или их подстроки. Но какие?
fn process<'x>(a &'x str, b: &str) -> &'x str {
...
}
Все, расходимся, это кусок ’a.
Исправление
vertexua,
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.
Лайфтаймы еще помогают в сигнатурах функций
fn process(a &str, b: &str) -> &str {
...
}
Тут не совсем ясно, мы одалживаем две строки, и возвращаем тоже ссылку на какую-то одолженую строку… Еее явно не создали внутри, так как все собственники внутри умерли по выходу из фунции. Стало быть это a
, b
или их подстроки. Но какие?
fn process<'a>(a &'a str, b: &str) -> &'a str {
...
}
Все, расходимся, это кусок ’a.
Исправление
vertexua,
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это не забота Client об этом парится. Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.
Исходная версия
vertexua,
:
Еще интересная вещь - лайфтаймы. Это самая сложная часть раста. Обычно без нее можно обойтись, но иногда нужно прямо совсем все заоптимизировать. Вернемся к вот этому.
в 3-4 местах в коде нужен какой-то FooManager и неизвестно кто будет последний ссылаться на него
Почему кстати неизвестно? Потому что я ленивый и мне все-равно. Влепил счетчик ссылок и разослал FooManager
в какие-то асинхронные лямбды.
Но допустим я знаю что все мое приложение существует внутри какой-то одной структуры которая существует дольше всего в моем приложении. Например так же как IoC контейнер в Java вроде Spring ApplicationContext.
В свои стуктуры я могу указать lifetime как шаблонный параметр, которым могу пользоваться для ссылок внутри этой стуктуры, доказывая что эти ссылки живут дольше чем моя структура, значит ей не нужно ими владеть и можно просто одалживать. Это намного круче чем одалживать внутрь функции - это хранить в структуре ссылку бесплатно и знать что собственник ее не уничтожит.
struct Client<'a> {
x: &'a FooManager;
}
impl Client {
fn use_x(self) {
self.x.call();
}
}
Client
живет время 'a
, а тот обьект на который ссылается «x» гарантировано живет дольше чем Client
, им владеет кто угодно другой, но живет он как минимум нужное время.
Это накладывает сразу ограничения на весь код, который создает FooManager
и Client
, но главная фича тут в том, что это *не забота Client об этом парится". Ссылка, нет владения, нет счетчика, полная бесплатность. Это все работает в безумных многопоточных приложениях, потому что на каждом шагу компилятор следит за временами жизни на этапе компиляции. Но в простом примере вот как.
let fm = FooManager{};
let client = Client{x: &fm}; // fm живет дольше client.
// Сначала невидимое освобождение client, только потом FooManager.