Rust中引用的生命周期(lifetime)问题:`e = &***c`时`e`的生命周期解析
e = &***c时e的生命周期解析 首先先看对应的代码示例:
fn lifetime_test<'a>(s: &'a String, t: &'a String) -> &'a String { s } fn main() { // let a; let mut a = String::from("hello1"); let b = &mut a; let e; { let c = &b; // e = c; // OK, move e = &***c; // OK, but why? // e = &*b; // OK, is *b same as a? // e = &a; // err, sure, a is borrowed // e = &c; // err, c lives not long enough // e = lifetime_test(c, b); // OK, because auto-dereference println!("{c}"); } println!("{b}"); // b.push_str("string"); let d = &b; println!("{d} {e}"); b.push_str("hello2"); a.push_str("hello3"); // println!("{}", l); }
问题核心
What is the lifetime of e when e = &***c?
原提问者的前置理解
bis a mutable reference toa, andcis an immutable reference tob.- I know that dereferencing
cthree times (&***c) should give me a reference toa(really?). But I’m unsure about how the lifetime of the referenceeworks here. - I understand that
citself is valid within the inner scope, andbis valid throughout the function. But I’m confused about whye = &***cworks whilee = &cgives an error (because c doesn’t live long enough).
详细解析
Let's break this down in plain, approachable terms:
First, let's map out all references and their lifespans clearly:
ais the originalStringinstance, created at the start ofmainand alive until the function ends.bis a mutable reference toa(&mut a), so its lifetime is directly tied toa—it's valid for the entiremainfunction.cis an immutable reference tob(&b), but it's declared inside the inner curly brace scope, so it dies as soon as that scope closes.
Now let's unpack what &***c actually does, step by step:
*cgives us the value ofb(the mutable reference&mut a), sincecpoints directly tob.**cgives us the value thatbpoints to: the originalStringa.***cmight look like we're dereferencinga(which isn't a reference, so that shouldn't compile)—but Rust's auto-dereferencing rules kick in here to collapse redundant operations. When you write&***c, Rust treats it as a direct reference to the ultimate target of the chain:a.
The critical "aha" moment is lifetime inheritance:
- When you write
&c, you're creating a reference tocitself. Sinceconly lives inside the inner scope, this reference's lifetime can't extend past that scope—hence the "c does not live long enough" error. - When you write
&***c, you're creating a reference toa, not tocorb. The lifetime of this new reference is tied toa(or tob's reference toa, which matchesa's lifetime), not toc. Even thoughcdies at the end of the inner scope,eis pointing directly toa—which is still alive for the rest ofmain.
A quick side note on why &***c is allowed when &a gives an error: a is already borrowed mutably by b, and Rust normally blocks mutable and immutable references from coexisting. But &***c is derived from the mutable reference b, so Rust's borrow checker recognizes this immutable reference is aliasing through b—and since we're not using e to mutate anything (and the mutable reference b is still usable later), it's permitted.
To answer your core question directly:
What is the lifetime of
ewhene = &***c?
The lifetime of e is the entire duration of the main function, matching the lifetime of a (and b). It's not tied to c at all—because e is ultimately a reference to the original String instance, not to any of the intermediate references in the chain.
You can confirm this by observing that e is used long after the inner scope closes (in println!("{d} {e}")) and that you can still modify a and b later—something that would be impossible if e's lifetime was tied to c.
备注:内容来源于stack exchange,提问作者htam_ujn

