Когда полезно определить несколько времен жизни в структуре?
В Rust, когда мы хотим, чтобы структура содержала ссылки, мы обычно определяем их время жизни как таковое:
struct Foo<'a> {
x: &'a i32,
y: &'a i32,
}
Но также можно определить несколько времен жизни для разных ссылок в одной и той же структуре:
struct Foo<'a, 'b> {
x: &'a i32,
y: &'b i32,
}
Когда это когда-нибудь полезно? Может ли кто-нибудь предоставить некоторый пример кода, который не компилируется, когда оба срока службы 'a
, но компилируются, когда время жизни 'a
и 'b
(или наоборот)?
Ответы
Ответ 1
После того, как вы задержались слишком поздно, я смог придумать примерный случай, когда жизнь имеет значение. Вот код:
static ZERO: i32 = 0;
struct Foo<'a, 'b> {
x: &'a i32,
y: &'b i32,
}
fn get_x_or_zero_ref<'a, 'b>(x: &'a i32, y: &'b i32) -> &'a i32 {
if *x > *y {
return x
} else {
return &ZERO
}
}
fn main() {
let x = 1;
let v;
{
let y = 2;
let f = Foo { x: &x, y: &y };
v = get_x_or_zero_ref(&f.x, &f.y);
}
println!("{}", *v);
}
Если вы изменили определение Foo
на следующее:
struct Foo<'a> {
x: &'a i32,
y: &'a i32,
}
Тогда код не будет компилироваться.
В принципе, если вы хотите использовать поля структуры для любой функции, для которой параметры должны иметь разные времена жизни, тогда поля структуры должны иметь разные времена жизни.
Ответ 2
Вот еще один простой пример, где определение структуры должно использовать два времени жизни, чтобы работать как ожидалось. Он не разбивает агрегат на поля с разными временами жизни, но объединяет структуру с другой структурой.
struct X<'a>(&'a i32);
struct Y<'a, 'b>(&'a X<'b>);
fn main() {
let z = 100;
//taking the inner field out of a temporary
let z1 = ((Y(&X(&z))).0).0;
assert!(*z1 == z);
}
Структура Y
имеет два параметра времени жизни: один для его ограниченного поля &X
и один для X
ограниченного поля &z
.
В операции ((Y(&X(&z))).0).0
X(&z)
создается как временный и заимствуется. Его время жизни находится только в области действия этой операции и заканчивается в конце оператора. Но поскольку время жизни X(&z)
отличается от содержащегося в нем поля &z
, вполне возможно вернуть операцию &z
, значение которой можно получить позже в функции.
Если используется одно время жизни для структуры Y
. Эта операция не будет работать, потому что время жизни &z
такое же, как и содержащая его структура X(&z)
, истекающая в конце оператора; поэтому возвращенный &z
больше не действителен для последующего доступа.
Смотрите код на детской площадке.