Как параметр времени жизни у структуры, содержащей ссылку, ограничивает срок существования экземпляра?
Параметр времени жизни у структуры гарантирует, что экземпляр структуры не будет использоваться дольше, чем доступен объект, на который ссылается. Он описывает связь между временем жизни ссылки внутри структуры и временем жизни самой структуры, но не продлевает жизнь исходного объекта и не управляет памятью во время выполнения.
В Rust безопасность ссылок обеспечивается на этапе компиляции без сборщика мусора и без постоянного отслеживания времени жизни объектов во время выполнения. Для этого компилятору нужно выразить, как долго ссылка внутри составного значения остаётся допустимой.
Параметры времени жизни решают проблему структур, содержащих заимствованные данные: без такой информации было бы невозможно доказать, что структура не переживёт объект, на который она ссылается.
Структура может хранить ссылку дольше, чем существует исходное значение. Тогда после уничтожения исходного значения ссылка стала бы висячей, а обращение к ней нарушило бы безопасность памяти.
Аннотация времени жизни не исправляет такую ситуацию автоматически. Она позволяет компилятору проверить связь: если экземпляр структуры доступен в некоторой области, то соответствующий объект-источник должен оставаться доступным как минимум столько же.
Параметр времени жизни структуры является ограничением для допустимых экземпляров, а не самостоятельным временем существования объекта. Если структура имеет ссылку с временем жизни 'a, то её значение нельзя использовать после окончания 'a.
Это ограничение может быть сформулировано так: структура не может пережить данные, которые она заимствует. При этом 'a не означает фиксированный интервал и не требует, чтобы ссылка жила максимально долго. Компилятор выбирает конкретную область действия, совместимую со всеми операциями использования.
Аннотация также не переносит владение данными в структуру и не освобождает их при уничтожении структуры. Структура лишь временно заимствует объект; владелец объекта по-прежнему отвечает за его существование.
Минимальный пример:
Здесь View<'a> может существовать только пока доступен source. Если попытаться вернуть такую структуру из функции вместе с уничтожаемой внутри функции строкой, компилятор отвергнет программу: аннотация не продлит жизнь локальной строки.
Если структура должна владеть данными независимо от источника, вместо ссылки используют владеющий тип, например String. Это устраняет ограничение заимствования, но обычно требует дополнительного выделения памяти или копирования.
Парсер возвращает представление части входного документа. Вариант с String для каждого найденного фрагмента прост с точки зрения владения, но может копировать большие объёмы текста и увеличивать расходы памяти.
Вариант с собственной ссылочной структурой экономичнее: все фрагменты ссылаются на исходный буфер, а время жизни структуры ограничено временем жизни этого буфера. Недостаток — такой результат нельзя сохранить или передать в независимый от буфера контекст.
Выбранное решение зависит от границ данных. Для краткоживущего конвейера «прочитать документ — обработать представления — завершить обработку» выбирают заимствованные представления. Для кэша или очереди, которая должна жить отдельно от входного буфера, выбирают владение данными или явное совместное владение, например через Arc.
Нет. Аннотация только сообщает компилятору требуемую связь между сроками использования. Если исходный объект локальный и уничтожается раньше структуры, добавление более длинной аннотации не сделает его доступным дольше; программа не скомпилируется.
Продлить срок существования можно изменением модели владения: например, передать владельца наружу, переместить данные в структуру или использовать подходящий владеющий контейнер. Аннотация сама по себе не является операцией управления памятью.
Нет, но это зависит от объявления структуры. Один параметр, например View<'a>, связывает все поля, использующие 'a, с общей гарантией: каждое такое поле должно быть допустимо в течение 'a.
Если поля могут заимствовать данные независимо, структуре можно задать несколько параметров времени жизни. Тогда одно поле может иметь более короткий срок, чем другое, однако экземпляр структуры всё равно нельзя использовать после окончания срока, необходимого для конкретной операции или поля.
'static для структуры со ссылкой?'static означает, что ссылка действительно допустима до конца работы программы. Это не универсальное требование и не способ «сделать» обычные данные статическими.
Указать 'static можно только для данных, которые фактически имеют такую продолжительность, например строкового литерала или значения, специально размещённого с этим временем жизни. Для ссылки на локальную строку это приведёт к ошибке, поскольку локальное значение не живёт до конца программы. Требование 'static часто чрезмерно ограничивает API и скрывает необходимость правильно выразить реальную связь между владельцем и заимствованными данными.