引用为什么安全 — 生命周期、签名即承诺、共享与互斥¶
这一章回答全书最硬的问题: 上一章的规矩凭什么查得动?答案是「生命周期」—— 给每个引用指派一段「它安全可用」的区间,约束解得开就过、解不开就拒。 然后是这个机制的两大红利:函数签名会暴露函数体的行为,以及一整类 C++ 经典 bug 被灭种。
1. 顶层全景:一个约束求解问题¶
每个引用类型 ⇒ 指派一个生命周期(程序中一段区间,编译期概念,运行时不存在)
│
├─ 约束A(上限):被借的值 x 的寿命必须【包含】引用的寿命
│ (x 先死了,引用就悬垂)
├─ 约束B(下限):存引用的变量 r 的寿命必须【被引用】包含
│ (引用活得比 r 短,r 就成悬垂指针)
▼
编译器:找一组同时满足所有约束的生命周期 —— 无解 ⇒ 拒绝编译
图说:本章所有例子——局部变量、函数、结构体——都是这两句约束的不同摆放。
2. 主线例子:最小的悬垂指针¶
Rust 的报错:x does not live long enough——x 死的时候还被借着1。
人眼看这错显而易见;值得看的是编译器怎么推出来的,因为同一套推理要扛住复杂得多的代码。
概念:生命周期(lifetime)。它是「一个引用可以安全使用的程序区间」——一条语句、一个表达式、 一个变量的作用域……原书特意强调:生命周期纯属编译期的想象;运行时引用就是一个地址, 生命周期是它类型的一部分,没有任何运行时表示2。
两句约束(用上面的例子):
- 约束 A(给寿命封顶):
&x的寿命不能超过 x 的作用域,否则就是悬垂指针—— 「变量的寿命必须包含从它借来的引用的寿命」3; - 约束 B(给寿命托底):存进 r 的引用,寿命必须覆盖 r 从初始化到最后一次使用—— 「引用的寿命必须包含存它的变量的寿命」4。
在这个例子里:A 要求寿命在 x 死前结束,B 要求寿命活到外块结束。无解,拒绝5。 反过来,若 r 的最后一次使用挪到内块里,A、B 就有交集了,代码通过6。
3. 函数签名:承诺写在你看得见的地方¶
3.1 把引用存进全局,签名必须说¶
主线例子升级:函数 f 想把参数存进全局变量(Rust 里叫 static,程序启动就在、退出才走)。
写出来长这样:
推理:STASH 活得和程序一样长,存进去的引用寿命也必须是 'static(整个程序);
而 f(p: &i32) 其实是 f<'a>(p: &'a i32) 的简写——「接受任何寿命的引用」。
「任何」当然包括短得只包住一次调用的寿命,存进 STASH 就悬垂——拒绝7。
想让函数只收能活到程序结束的引用?把签名改成 p: &'static i328。
作者让这一步的分量显形:从 f(p: &i32) 到 f(p: &'static i32),函数的签名忠实记录了函数体的行为——
在 Rust 里,不把这个意图写进签名,函数就写不出来。「函数签名总是暴露函数体的行为」9。
推论同样值钱:看到 g(p: &i32),不用看函数体就知道 g 不会把 p 存到活得比这次调用久的地方;
想确认一次调用的安全性,只读签名就够10。
3.2 返回引用:寿命绑回参数¶
函数拿了引用、又返回引用,返回的指向谁?Rust 的省略规则假定:参数和返回值同一寿命。
fn smallest(v: &[i32]) -> &i32 展开是 fn smallest<'a>(v: &'a [i32]) -> &'a i3211。
后果:返回值借自参数所指的数据。把这个结果存得比数据源还久,无解,拒绝:
let s;
{
let parabola = [9, 4, 1, 0, 1, 4, 9];
s = smallest(¶bola);
} // parabola 死
assert_eq!(*s, 0); // 错误:s 指向已死的数组元素
把 s 挪进内块,约束就有解了12。
3.3 结构体里的引用:寿命参数传染¶
引用藏进结构体,安全约束不会 magically 消失——它们必须传染到 S 自己身上。
要么写死 'static(很受限:只能借程序全程存活的东西),要么给类型自己的寿命参数:
每个 S 值的 'a 由用法决定:存进 r 的引用寿命要包住 'a;'a 要撑住 S 活的地方13。
而 S 再被包进 D,D 也得声明寿命参数(或者只用 S<'static>)——传染到底14。
为什么逼你写?Rust 早期版本自动给每个引用造隐形寿命,开发者发现很迷惑:
知道「一个值从另一个值借了东西」对排错极有帮助,所以改成显式15。
类型签名由此也成为承诺:fn parse_record<'i>(input: &'i [u8]) -> Record<'i>
不用看 Record 的定义就知道——Record 里的引用指向传进来的 buffer,不会指向别处16。
3.4 完整代码重放:结构体传染的两级现场¶
把书里 S、D 两个结构体的完整推演走一遍,体会「传染」是怎么逐层发生的40。
第一级:引用直接作字段。
错误的原因上一节说了:引用藏进结构体,安全约束必须跟着传染到 S 身上,而传染的载体 就是 S 自己的寿命参数。修正:
第二级:S 被 D 包进去。
S 本身带参数,D 就必须表态:要么只用 S<'static>(那 D 就不能借局部变量了,
但 D 自己无任何限制),要么 D 也领一个参数传给 S:
两级推演,规则一条:谁的类型里出现带参数的引用(或带参数的 S),谁就得带参数。 没有例外、没有「编译器帮我记着」——早期的 Rust 曾自动记,被开发者否了, 理由是「知道一个值从另一个值借了东西,对排错太重要了」41。
3.5 完整代码重放:返回引用绑回参数¶
书上这个函数很小,却是「签名即承诺」的最佳标本:
// v 至少要有一个元素
fn smallest(v: &[i32]) -> &i32 {
let mut s = &v[0];
for r in &v[1..] {
if *r < *s { s = r; }
}
s
}
省略规则把它补成 fn smallest<'a>(v: &'a [i32]) -> &'a i32——
输入切片和返回引用共用一条命。这个签名向外声明两件事:
调用方传进来的切片,返回值指向它的内部;调用方不能让返回值活得比切片久。
两种常见的死法因此编译不过:
let s;
{
let parabola = [9, 4, 1, 0, 1, 4, 9];
s = smallest(¶bola);
} // parabola 在这里死
assert_eq!(*s, 0); // 错误:s 指向死掉的数组元素
把 s 挪进内块,约束立刻有解——编译器只看「值的寿命 ⊇ 引用寿命 ⊇ 变量寿命」
能不能同时成立,不关心代码写起来「显然没问题」42。
3.6 调用方视角:编译器替你挑最短的寿命¶
签名是承诺,调用是履约。看同一个 g 的两个调用47:
从 g 的签名我们知道:它不会把 p 存到活得比这次调用久的地方——任何包住调用的寿命
都满足 'a。所以编译器给 &x 挑最短的候选:恰好包住这次调用的那一点。
约束全过:不比 x 活得长(它在 x 作用域内),也不比调用短(覆盖了整个调用)。
调用方一个寿命字都不用写48。
反过来,把 &x 传给前面那个存全局的 f(p: &'static i32) 呢?
&x 最多活到 x 死,而 f 要求活到程序结束——无解,拒。
同一段 &x,函数签名决定它能不能去——这就是「签名即承诺」在调用侧的读法49。
3.7 statics 的两条军规¶
那个存引用的全局变量例子顺带交代了 Rust 静态变量(static,程序启动就在、 退出才走的值)的两条军规50:
- 必须初始化——没有「先声明后赋值」的余地;
- 可变的静态量天生线程不安全(任何线程随时能摸它,单线程下也有重入问题),
只能在
unsafe块里访问。
第二条和第 5 节的并发结论对上号:共享 + 可变 = 危险,这条等式在静态量上也不打折扣。
借的是大结构的一部分:约束自动上溯¶
规则对「借一部分」自动生效,不用你额外声明。借向量一个元素的引用:
v 拥有向量,向量拥有元素,所以「v 的寿命 ⊇ 引用的寿命」这条约束, 自动沿着拥有链传导到元素身上。同样,把引用存进数据结构,引用的寿命就必须包住 整个结构的寿命——若你造了一个装满引用的向量,每条引用的寿命都得盖住那个向量51。
这就是约束求解不需要「特殊情形」的原因:所有规则都是同一句「值的寿命 ⊇ 引用寿命」 在不同摆放下的复读,向量、结构体、HashMap、嵌套三层,一视同仁。
4. 省略:三种默认规则¶
并不是处处都要写寿命。Rust 的省略规则17:
| 情形 | 默认 |
|---|---|
| 参数里的引用 | 每个位置一个独立的新寿命 |
| 只有一个输入寿命时,返回值里的寿命 | 就是那个输入寿命 |
&self 方法(方法是挂在类型上的函数,self 就是被调的那个值) |
返回值寿命一律取 &self 的 |
fn first_third(point: &[i32; 3]) -> (&i32, &i32) 自动补成 <'a>(point: &'a [i32; 3]) -> (&'a i32, &'a i32)18;
find_by_prefix(&self, prefix: &str) -> Option<&String> 自动补成 Option<&'a String>——
「你从 self 里借东西」19。
约束写太紧怎么办?一个结构体两个引用共用一个 'a,会被迫同生共死;
拆成 <'a, 'b> 就各活各的20。函数签名同理。
作者的建议很务实:先写最简单的,编译器拒绝再放宽——反正不安全就编译不过,等它告诉你21。
4.1 过紧现场:两个引用被迫同生共死¶
省略规则省心,但有一种经典的「太紧」值得亲手踩一遍43。
struct S<'a> {
x: &'a i32,
y: &'a i32, // 与 x 共用一条命 'a
}
let x = 10;
let r;
{
let y = 20;
{
let s = S { x: &x, y: &y };
r = s.x; // 把 x 的那份引用留下来
} // s 死
} // y 死
println!("{r}"); // r 指向 x,活着——这段代码其实没问题
但 Rust 会拒:complains that y does not live long enough。推理:
- 两个字段共用一个
'a,编译器得给 s.x 和 s.y 找一条同时管用的寿命; r = s.x要求'a包住 r 的寿命(r 用到外块结束);s.y = &y要求'a不超过 y 的寿命(y 在内块死)。
要 'a 比 y 短、又比 r 长——不存在这样的区间44。
修复:给两个字段各发一条命。
'a 取 r 的寿命,'b 取 s 的寿命,各不相欠,编译通过。
函数签名同款:参数挤一个 'a 会过度约束调用方,拆开 'a, 'b 就松了45。
代价作者也明说了:寿命越多,签名越难读。他们的习惯是先最简、报错再松—— 反正报的都是编译错误,等编译器开口毫无风险46。
5. 共享与互斥:一整类 bug 的灭种¶
5.1 两条规则的正式版¶
回到上一章的规矩,这里给机制上的理由。悬垂还有别的造法:值被搬走了,引用还活着:
let v = vec![4, 8, 19, 27, 34, 10];
let r = &v;
let aside = v; // 搬走 v,r 悬垂
r[0]; // 错误:cannot move out of `v` because it is borrowed
v 明明在 r 的整段寿命里都「在作用域内」——但值被搬走了,等于死了却没退出作用域。 所以共享引用活着时,它到被借值之间的整条所有权路径都被冻结:不许赋值、不许移动22。
第二条路线的名场面:往正在指着的向量里加元素。
Casual 看没问题。但如果 wave 容量不够,push 会换一块更大的缓冲,旧缓冲释放——
而 &wave 指向的旧缓冲上的切片立刻悬垂。这类 bug 的阴险处:测试时容量总是够,永不触发23。
C++ 的 std::vector 规范白纸黑字:「重分配使指向元素的引用、指针、迭代器全部失效」;
Java 的 Hashtable 结构被改时迭代器直接抛 ConcurrentModificationException——
家家都有这坑,只是别的语言在运行时撞见,Rust 在编译时拒绝:extend(&mut wave, &wave) 同时借了可变和共享,互斥24。
5.2 两条规则的原话¶
原书把它们写成两条,值得原文照录其义:
共享访问即只读访问。 共享引用借着的值,从它能到达的一切路径都被冻结: 没有任何活的可变引用通向它,主人也只读。
可变访问即排他访问。 可变引用活着时,通向它的值不存在第二条可用路径—— 唯一能与之共存的引用,是从这个可变引用自己再借出去的25。
注意范围:冻结的不只是被借的值本身,而是指向它的整条路径和它能到达的一切。 你借了 HashMap 里一个键的共享引用,整个 HashMap 直到引用死前都拒绝可变借用26。
5.3 灭种名单¶
书里点名的三个 C++ 经典 bug,其实是同一类:
| C++ 的 bug | 形状 | Rust 的下场 |
|---|---|---|
自赋值翻车:f = f 把正要复制的资源先关了 |
「以为在读 A、其实在改 A」 | clone_from(&mut f, &f) 直接编译失败 |
| 迭代器失效:边遍历边改容器 | 同上 | 共享借用期间禁止可变借用 |
| memcpy/strcpy 源和目标重叠 | 同上 | 可变访问排他,重叠借不出来 |
作者的总结:两个经典 C++ bug——没处理自赋值、用了失效迭代器——是同一个底层 bug 的两种形态; 让可变访问排他,Rust 把这一整类日常错误挡在门外27。
5.4 并发:数据竞争按构造消失¶
这是两条规则最大的红利。数据竞争的定义:某个值既可变、又被跨线程共享—— 「恰好就是 Rust 引用规则消灭的那个形状」。所以一个不用 unsafe 的 Rust 并发程序, 按构造( by construction)无数据竞争28。第 1 章那个「编译过即无数据竞争」的承诺,到这里才有了根据。
6. 设计层面的余波:sea of objects 的减速带¶
垃圾回收时代以来,程序默认的架构是对象之海:什么都指什么,几年后没人说得清依赖关系, 「几年之后,你会有充分的理由重写一遍(放 AC/DC 的《通往地狱的高速公路》)」——原书的原话带刺29。
Rust 的所有权模型给这条高速公路装了减速带:在 Rust 里造一个环(两个值互相指)要费点劲—— 得动用 Rc 加内部可变性(还没讲的特性);Rust 偏爱指针、所有权、数据流(数据在部件之间的流动)单向穿过系统的一棵树30。
作者给读者的警告也在这里:读完本章别冲出去用 Rc 连一片「结构体之海」, 复刻你熟悉的那套面向对象反模式——Rust 会让你碰钉子。药方是做前期设计,建更好的程序31。 全书的态度浓缩为一句:「Rust 就是把理解你的程序的痛苦,从未来挪到现在」32。
7. 作者的判断与证据¶
- 约束求解的推理过程(§2)是机制描述,可信;「运行时零成本」由「生命周期无运行时表示」直接成立2。
- 「自赋值与迭代器失效是同一种 bug」是作者的归纳,有 C++ 规范原文撑腰(引文见 §5.1)23。
- 「等编译器告诉你,再放宽签名」是作者自己的工程习惯,被写成建议21。
- 「痛苦挪到现在」是立场句,同时是准确的工程观察——前期设计成本换后期调试成本。
8. 边界与局限¶
- 省略规则有三条默认,但高阶场景(闭包返回引用、
impl块里的复杂签名)仍需手写,本章只给了入门集; &mut重借(reborrow)在嵌套调用里的精确规则没有展开;- 「按构造无数据竞争」只覆盖无 unsafe 的代码;unsafe 块里一切靠自己;
- sea of objects 的讨论是定性分析,没有案例数据。
9. 可带走的¶
主线例子一行版: r = &x 后 x 先死 → 约束 A(值包引用)与约束 B(引用包变量)无解 → 拒绝编译。
- 生命周期 = 引用可安全使用的程序区间;纯编译期概念,运行时引用只是地址;
- 约束两句:被借值的寿命 ⊇ 引用寿命;引用寿命 ⊇ 存引用变量的寿命;
- 函数签名必须如实记录引用去向:存全局就得写
&'static,否则写不出来; - 读签名即知函数行为:返回引用绑回参数;不看函数体也知道它不会把参数藏起来;
- 结构体含引用 ⇒ 类型必须有寿命参数,且传染到外层类型——签名即承诺;
- 省略规则:单输入寿命绑返回值;
&self方法返回值绑 self;多输入寿命要写; - 写太紧就拆
'a, 'b;先简后繁,等编译器拒绝再放宽; - 共享借用在,整条路径冻结(不许移动、可变);可变借用在,排他;
- 自赋值、迭代器失效、memcpy 重叠是同一类 bug——「可变即排他」全部灭种;
- 数据竞争的定义形状被引用规则预先排除:无 unsafe ⟹ 并发按构造安全。
10. 每个类型都有寿命——多数类型是 'static¶
一个容易滑过去的普遍化(原书第 599 段):不只是引用和有引用的结构体有寿命,Rust 里每个类型都有。
大多数类型的寿命是 'static——意思是「这种类型的值想活多久活多久」:
Vec<i32> 自包含,不必赶在哪个变量死之前先死;i32、String 也一样33。
但只要类型里掺了引用,寿命就矮一截:Vec<&'a i32> 的寿命被 'a 压着头,
必须在它指的那些整数还活着的时候先死掉。给类型标寿命,等于在类型上挂了张「此物有保质期」的标签,
编译器按标签安排检查的顺序34。
回看签名即承诺那条:一个类型有没有寿命参数、参数叫什么,就是它含不含借用的公开声明。
Record<'i> 一眼能看出它借了输入缓冲;i32 一眼能看出它谁也没借。这就是为什么 Rust
坚持让寿命参数写在明面上——它不只是检查的需要,也是读代码时的路标35。
11. 省略规则的三个完整案例¶
规则是抽象的,原书给了三个展开的案例,值得各看一眼。
案例一:多个参数各自独立。 fn sum_r_xy(r: &i32, s: S) -> i32 展开成
fn sum_r_xy<'a, 'b, 'c>(r: &'a i32, s: S<'b, 'c>) -> i32——
每个需要寿命的位置都分到一个全新、互不相干的寿命,谁也不欠谁36。
案例二:单输入寿命绑返回值。 fn first_third(point: &[i32; 3]) -> (&i32, &i32)
展开成 fn first_third<'a>(point: &'a [i32; 3]) -> (&'a i32, &'a i32)。
返回值里的两个引用,都指向参数的数组——既然只有一个候选,就全绑给它37。
案例三:&self 一锤定音。 方法是挂在类型上的函数,self 就是被调的那个值
(Rust 里的 this)。fn find_by_prefix(&self, prefix: &str) -> Option<&String> 展开成
fn find_by_prefix<'a, 'b>(&'a self, prefix: &'b str) -> Option<&'a String>:
返回值不绑 prefix,绑 self——「你从自己身上借东西」。
这个默认非常符合直觉:按前缀查表,找到的自然是表里(不是前缀里)的字符串38。
三条记不住没关系,作者给了护身策略:先写最简形态,编译器拒绝再补—— 寿命写错了永远是编译错误,不是运行时事故,等编译器开口是最省力的学法39。
12. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 生命周期的定义 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:339(搜「figments」) |
| 约束 A:值包引用 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:345(搜「contain or enclose」) |
| 约束 B:引用包变量 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:351(搜「contain or enclose」) |
| 最小悬垂例子与报错 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:326(搜「does not live long enough」) |
| 'static 与全局变量 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:405(搜「'static lifetime」) |
| 签名暴露行为 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:432(搜「signature always exposes」) |
| smallest 返回引用 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:465(搜「smallest」) · text/14-ch04-chapter-4-references.txt:486(搜「same lifetime」) |
| 结构体缺寿命报错 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:526(搜「missing lifetime specifier」) |
| 传染到外层类型 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:552(搜「not adequate」) |
| 为什么逼你写寿命 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:597(搜「confusing」) |
| 拆寿命参数 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:601(搜「Distinct Lifetime」) · text/14-ch04-chapter-4-references.txt:642(搜「independent」) |
| 等编译器拒绝再放宽 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:652(搜「loosen restrictions」) |
| 省略规则 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:673(搜「single lifetime」) · text/14-ch04-chapter-4-references.txt:685(搜「self parameter」) |
| 向量扩容失效引用 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:771(搜「eight elements」) · text/14-ch04-chapter-4-references.txt:775(搜「invalidates」) |
| 两条规则原文 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:796(搜「read-only access」) · text/14-ch04-chapter-4-references.txt:798(搜「exclusive access」) |
| 自赋值 bug 灭种 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:908(搜「self-assignment」) · text/14-ch04-chapter-4-references.txt:908(搜「overlap」) |
| 数据竞争按构造消失 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:910(搜「by construction」) |
| sea of objects 与减速带 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:936(搜「sea of objects」) · text/14-ch04-chapter-4-references.txt:946(搜「speed bump」) |
| 痛苦挪到现在 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:952(搜「transferring the pain」) |
| 每个类型都有寿命 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:599(搜「Every type」) |
| 结构体传染的完整现场 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:526(搜「missing lifetime specifier」) |
| smallest 返回引用 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:465(搜「smallest」) |
| 两个引用共用一个寿命的过紧现场 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:601(搜「Distinct」) |
| 调用方视角:最短寿命 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:447(搜「smallest possible lifetime」) |
| statics 的两条军规 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:382(搜「Every static」) |
| 借大结构的一部分:约束上溯 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:368(搜「owns the vector」) |
| 省略规则三案例 | Chapter 4. References | text/14-ch04-chapter-4-references.txt:665(搜「sum_r_xy」) · text/14-ch04-chapter-4-references.txt:675(搜「first_third」) · text/14-ch04-chapter-4-references.txt:694(搜「find_by_prefix」) |
-
出处:「Chapter 4. References」第 321–335 段(
text/14-ch04-chapter-4-references.txt:321-335,搜「does not live long enough」)。 ↩ -
出处:「Chapter 4. References」第 339 段(
text/14-ch04-chapter-4-references.txt:339,搜「figments」)。 ↩↩ -
出处:「Chapter 4. References」第 345 段(
text/14-ch04-chapter-4-references.txt:345,搜「contain or enclose」)。 ↩ -
出处:「Chapter 4. References」第 351 段(
text/14-ch04-chapter-4-references.txt:351,搜「contain or enclose」)。 ↩ -
出处:「Chapter 4. References」第 357 段(
text/14-ch04-chapter-4-references.txt:357,搜「contradictory」)。 ↩ -
出处:「Chapter 4. References」第 359–361 段(
text/14-ch04-chapter-4-references.txt:359-361,搜「meets the constraints」)。 ↩ -
出处:「Chapter 4. References」第 395–413 段(
text/14-ch04-chapter-4-references.txt:395-413,搜「may not live long enough」)。 ↩ -
出处:「Chapter 4. References」第 415–430 段(
text/14-ch04-chapter-4-references.txt:415-430,搜「compiles just fine」)。 ↩ -
出处:「Chapter 4. References」第 432 段(
text/14-ch04-chapter-4-references.txt:432,搜「signature always exposes」)。 ↩ -
出处:「Chapter 4. References」第 434 段(
text/14-ch04-chapter-4-references.txt:434,搜「no need to look」)。 ↩ -
出处:「Chapter 4. References」第 462–475 段(
text/14-ch04-chapter-4-references.txt:462-475,搜「same lifetime」)。 ↩ -
出处:「Chapter 4. References」第 477–504 段(
text/14-ch04-chapter-4-references.txt:477-504,搜「parabola」)。 ↩ -
出处:「Chapter 4. References」第 524–547 段(
text/14-ch04-chapter-4-references.txt:524-547,搜「fresh lifetime」)。 ↩ -
出处:「Chapter 4. References」第 549–587 段(
text/14-ch04-chapter-4-references.txt:549-587,搜「not adequate」)。 ↩ -
出处:「Chapter 4. References」第 597 段(
text/14-ch04-chapter-4-references.txt:597,搜「confusing」)。 ↩ -
出处:「Chapter 4. References」第 593–595 段(
text/14-ch04-chapter-4-references.txt:593-595,搜「parse_record」)。 ↩ -
出处:「Chapter 4. References」第 656–671 段(
text/14-ch04-chapter-4-references.txt:656-671,搜「omit」)。 ↩ -
出处:「Chapter 4. References」第 673–681 段(
text/14-ch04-chapter-4-references.txt:673-681,搜「single lifetime」)。 ↩ -
出处:「Chapter 4. References」第 685–708 段(
text/14-ch04-chapter-4-references.txt:685-708,搜「self parameter」)。 ↩ -
出处:「Chapter 4. References」第 603–642 段(
text/14-ch04-chapter-4-references.txt:603-642,搜「independent lifetimes」)。 ↩ -
出处:「Chapter 4. References」第 652 段(
text/14-ch04-chapter-4-references.txt:652,搜「loosen restrictions」)。 ↩↩ -
出处:「Chapter 4. References」第 714–727 段(
text/14-ch04-chapter-4-references.txt:714-727,搜「moved elsewhere」)。 ↩ -
出处:「Chapter 4. References」第 769–779 段(
text/14-ch04-chapter-4-references.txt:769-779,搜「invalidates」)。 ↩↩ -
出处:「Chapter 4. References」第 781–792 段(
text/14-ch04-chapter-4-references.txt:781-792,搜「cannot borrow」)。 ↩ -
出处:「Chapter 4. References」第 794–799 段(
text/14-ch04-chapter-4-references.txt:794-799,搜「read-only access」与「exclusive access」)。 ↩ -
出处:「Chapter 4. References」第 848 段(
text/14-ch04-chapter-4-references.txt:848,搜「HashMap」)。 ↩ -
出处:「Chapter 4. References」第 908 段(
text/14-ch04-chapter-4-references.txt:908,搜「same underlying kind of bug」)。 ↩ -
出处:「Chapter 4. References」第 910 段(
text/14-ch04-chapter-4-references.txt:910,搜「by construction」)。 ↩ -
出处:「Chapter 4. References」第 936–942 段(
text/14-ch04-chapter-4-references.txt:936-942,搜「sea of objects」)。 ↩ -
出处:「Chapter 4. References」第 946 段(
text/14-ch04-chapter-4-references.txt:946,搜「speed bump」)。 ↩ -
出处:「Chapter 4. References」第 950 段(
text/14-ch04-chapter-4-references.txt:950,搜「sea of structs」)。 ↩ -
出处:「Chapter 4. References」第 952 段(
text/14-ch04-chapter-4-references.txt:952,搜「transferring the pain」)。 ↩ -
出处:「Chapter 4. References」第 599 段(
text/14-ch04-chapter-4-references.txt:599,搜「Every type」)。 ↩ -
出处:「Chapter 4. References」第 599 段(
text/14-ch04-chapter-4-references.txt:599,搜「must be dropped」)。 ↩ -
出处:「Chapter 4. References」第 589–597 段(
text/14-ch04-chapter-4-references.txt:589-597,搜「roadside」)。「这就是 Rust 要求含引用的类型显式带寿命参数的原因」一节。 ↩ -
出处:「Chapter 4. References」第 665–671 段(
text/14-ch04-chapter-4-references.txt:665-671,搜「distinct lifetime」)。 ↩ -
出处:「Chapter 4. References」第 673–681 段(
text/14-ch04-chapter-4-references.txt:673-681,搜「single lifetime」)。 ↩ -
出处:「Chapter 4. References」第 685–708 段(
text/14-ch04-chapter-4-references.txt:685-708,搜「self parameter」)。 ↩ -
出处:「Chapter 4. References」第 652 段(
text/14-ch04-chapter-4-references.txt:652,搜「perfectly acceptable tactic」)。 ↩ -
出处:「Chapter 4. References」第 508–587 段(
text/14-ch04-chapter-4-references.txt:508-587,搜「expected lifetime parameter」)。 ↩ -
出处:「Chapter 4. References」第 597 段(
text/14-ch04-chapter-4-references.txt:597,搜「confusing」)。 ↩ -
出处:「Chapter 4. References」第 462–504 段(
text/14-ch04-chapter-4-references.txt:462-504,搜「smallest」)。 ↩ -
出处:「Chapter 4. References」第 601–642 段(
text/14-ch04-chapter-4-references.txt:601-642,搜「does not create any dangling」)。 ↩ -
出处:「Chapter 4. References」第 625–633 段(
text/14-ch04-chapter-4-references.txt:625-633,搜「impossible to satisfy」)。 ↩ -
出处:「Chapter 4. References」第 644–650 段(
text/14-ch04-chapter-4-references.txt:644-650,搜「looser」)。 ↩ -
出处:「Chapter 4. References」第 652 段(
text/14-ch04-chapter-4-references.txt:652,搜「perfectly acceptable tactic」)。 ↩ -
出处:「Chapter 4. References」第 436–458 段(
text/14-ch04-chapter-4-references.txt:436-458,搜「smallest possible lifetime」)。 ↩ -
出处:「Chapter 4. References」第 447–449 段(
text/14-ch04-chapter-4-references.txt:447-449,搜「You only need to worry」)。 ↩ -
出处:「Chapter 4. References」第 453–458 段(
text/14-ch04-chapter-4-references.txt:453-458,搜「no way to satisfy」)。 ↩ -
出处:「Chapter 4. References」第 380–386 段(
text/14-ch04-chapter-4-references.txt:380-386,搜「Every static」)。 ↩ -
出处:「Chapter 4. References」第 363–368 段(
text/14-ch04-chapter-4-references.txt:363-368,搜「owns the vector」)。 ↩