diff --git a/po/zh-CN.po b/po/zh-CN.po index 08cbedb2..2bb73c76 100644 --- a/po/zh-CN.po +++ b/po/zh-CN.po @@ -4371,7 +4371,7 @@ msgstr "" #: src/ownership.md:1 msgid "# Ownership" -msgstr "" +msgstr "# 所有权" #: src/ownership.md:3 msgid "" @@ -4379,6 +4379,8 @@ msgid "" "to\n" "use a variable outside its scope:" msgstr "" +"所有变量绑定都有一个有效的“作用域”,使用\n" +"超出其作用域的变量是错误的:" #: src/ownership.md:6 msgid "" @@ -4394,6 +4396,17 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" #: src/ownership.md:18 msgid "" @@ -4401,14 +4414,17 @@ msgid "" "* A destructor can run here to free up resources.\n" "* We say that the variable _owns_ the value." msgstr "" +"* 作用域结束时,变量会“被丢弃”,数据会被释放。\n" +"* 析构函数可在此运行以释放资源。\n" +"* 指出变量“拥有”值。" #: src/ownership/move-semantics.md:1 msgid "# Move Semantics" -msgstr "" +msgstr "# 移动语义" #: src/ownership/move-semantics.md:3 msgid "An assignment will transfer ownership between variables:" -msgstr "" +msgstr "赋值操作将在变量之间转移所有权:" #: src/ownership/move-semantics.md:5 msgid "" @@ -4421,6 +4437,14 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" #: src/ownership/move-semantics.md:14 msgid "" @@ -4430,6 +4454,11 @@ msgid "" "* When `s2` goes out of scope, the string data is freed.\n" "* There is always _exactly_ one variable binding which owns a value." msgstr "" +"* 将 `s1` 赋值给 `s2`,即转移了所有权。\n" +"* 数据从 `s1`“移出”,且 `s1` 不再可供访问。\n" +"* 当 `s1` 离开作用域时,什么都不会发生:它没有所有权。\n" +"* 当 `s2` 离开作用域时,字符串数据被释放。\n" +"* 变量绑定在任一时刻有且“只有”一个值。" #: src/ownership/move-semantics.md:22 msgid "" @@ -4438,10 +4467,14 @@ msgid "" "\n" "* In Rust, clones are explicit (by using `clone`)." msgstr "" +"* 指出这与 C++ 中的默认值相反。除非你使用 `std::move`(并已定义 move 构造函" +"数!),否则 C++ 中的默认值是按值复制的。\n" +"\n" +"* 在 Rust 中,克隆是显式的(通过使用 `clone`)。" #: src/ownership/moved-strings-rust.md:1 msgid "# Moved Strings in Rust" -msgstr "" +msgstr "# Rust 中移动的字符串" #: src/ownership/moved-strings-rust.md:3 msgid "" @@ -4452,16 +4485,24 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" #: src/ownership/moved-strings-rust.md:10 msgid "" "* The heap data from `s1` is reused for `s2`.\n" "* When `s1` goes out of scope, nothing happens (it has been moved from)." msgstr "" +"* `s1` 中的堆数据会被 `s2` 重复使用。\n" +"* 当 `s1` 离开作用域时,什么都不会发生(它已被移出)。" #: src/ownership/moved-strings-rust.md:13 msgid "Before move to `s2`:" -msgstr "" +msgstr "移动到 `s2` 中之前:" #: src/ownership/moved-strings-rust.md:15 msgid "" @@ -4480,10 +4521,24 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" 栈 堆\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/ownership/moved-strings-rust.md:30 msgid "After move to `s2`:" -msgstr "" +msgstr "移动到 `s2` 中之后:" #: src/ownership/moved-strings-rust.md:32 msgid "" @@ -4508,14 +4563,34 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" 栈 堆\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(无法访问)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/ownership/double-free-modern-cpp.md:1 msgid "# Double Frees in Modern C++" -msgstr "" +msgstr "# 现代 C++ 中的双重释放" #: src/ownership/double-free-modern-cpp.md:3 msgid "Modern C++ solves this differently:" -msgstr "" +msgstr "现代 C++ 以不同的方式解决此问题:" #: src/ownership/double-free-modern-cpp.md:5 msgid "" @@ -4524,6 +4599,10 @@ msgid "" "std::string s2 = s1; // Duplicate the data in s1.\n" "```" msgstr "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // 复制 s1 中的数据。\n" +"```" #: src/ownership/double-free-modern-cpp.md:10 msgid "" @@ -4531,10 +4610,12 @@ msgid "" "copy.\n" "* When `s1` and `s2` go out of scope, they each free their own memory." msgstr "" +"* `s1` 中的堆数据被复制,`s2` 获得自己的独立副本。\n" +"* 当 `s1` 和 `s2` 离开作用域时,它们会各自释放自己的内存。" #: src/ownership/double-free-modern-cpp.md:13 msgid "Before copy-assignment:" -msgstr "" +msgstr "复制-赋值之前:" #: src/ownership/double-free-modern-cpp.md:16 msgid "" @@ -4552,10 +4633,23 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" 栈 堆\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/ownership/double-free-modern-cpp.md:30 msgid "After copy-assignment:" -msgstr "" +msgstr "复制-赋值之后:" #: src/ownership/double-free-modern-cpp.md:32 msgid "" @@ -4580,16 +4674,38 @@ msgid "" "`- - - - - - - - - - - - - -'\n" "```" msgstr "" +"```bob\n" +" 栈 堆\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" #: src/ownership/moves-function-calls.md:1 msgid "# Moves in Function Calls" -msgstr "" +msgstr "# 函数调用中的移动" #: src/ownership/moves-function-calls.md:3 msgid "" "When you pass a value to a function, the value is assigned to the function\n" "parameter. This transfers ownership:" msgstr "" +"你将值传递给函数时,该值会被赋给函数\n" +"参数。这就转移了所有权:" #: src/ownership/moves-function-calls.md:6 msgid "" @@ -4605,6 +4721,17 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" #: src/ownership/moves-function-calls.md:20 msgid "" @@ -4620,15 +4747,23 @@ msgid "" "move semantics the default, and by forcing programmers to make clones " "explicit." msgstr "" +"* 首次调用 `say_hello` 时,`main` 便放弃了 `name` 的所有权。此后,`main` 中不" +"能再使用 `name`。\n" +"* 在 `say_hello` 函数结束时,系统会释放为 `name` 分配的堆内存。\n" +"* 如果 `main` 将 `name` 作为引用 (`&name`) 传递过去,且 `say_hello` 接受作为" +"参数的引用,则可保留所有权。\n" +"* 此外,`main` 也可以在首次调用时传递 `name` 的克隆 (`name.clone()`)。\n" +"* 相较于 C++,Rust 通过将移动语义设为默认值,并强制程序员进行显式克隆,更难以" +"无意中创建副本。" #: src/ownership/copy-clone.md:1 msgid "# Copying and Cloning" -msgstr "" +msgstr "# 复制和克隆" #: src/ownership/copy-clone.md:3 msgid "" "While move semantics are the default, certain types are copied by default:" -msgstr "" +msgstr "虽然移动语义是默认的,但默认情况下会复制某些类型:" #: src/ownership/copy-clone.md:5 msgid "" @@ -4641,14 +4776,22 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" #: src/ownership/copy-clone.md:14 msgid "These types implement the `Copy` trait." -msgstr "" +msgstr "这些类型实现了 `Copy` trait。" #: src/ownership/copy-clone.md:16 msgid "You can opt-in your own types to use copy semantics:" -msgstr "" +msgstr "你可以选择自己的类型来使用复制语义:" #: src/ownership/copy-clone.md:18 msgid "" @@ -4664,16 +4807,29 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" #: src/ownership/copy-clone.md:30 msgid "" "* After the assignment, both `p1` and `p2` own their own data.\n" "* We can also use `p1.clone()` to explicitly copy the data." msgstr "" +"* 赋值之后,`p1` 和 `p2` 都拥有自己的数据。\n" +"* 我们还可以使用 `p1.clone()` 显式复制数据。" #: src/ownership/copy-clone.md:35 msgid "Copying and cloning are not the same thing:" -msgstr "" +msgstr "复制和克隆是两码事:" #: src/ownership/copy-clone.md:37 msgid "" @@ -4685,10 +4841,14 @@ msgid "" "implementing the `Clone` trait.\n" "* Copying does not work on types that implement the `Drop` trait." msgstr "" +"* 复制是指内存区域的按位复制,不适用于任意对象。\n" +"* 复制不允许自定义逻辑(不同于 C++ 中的复制构造函数)。\n" +"* 克隆是一种更通用的操作,也允许通过实现 `Clone` trait 来自定义行为。\n" +"* 复制不适用于实现 `Drop` trait 的类型。" #: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 msgid "In the above example, try the following:" -msgstr "" +msgstr "在上述示例中,请尝试以下操作:" #: src/ownership/copy-clone.md:44 msgid "" @@ -4698,6 +4858,11 @@ msgid "" "the `println!` for `p1`.\n" "* Show that it works if you clone `p1` instead." msgstr "" +"* 在 `struct Point` 中添加 `String` 字段。由于 `String` 不属于 `Copy` 类型," +"因此无法编译。\n" +"* 从 `derive` 属性中移除 `Copy`。现在,编译器错误位于 `p1`的 `println!` " +"中。\n" +"* 指出如果你改为克隆 `p1`,则可按预期运行。" #: src/ownership/copy-clone.md:48 msgid "" @@ -4706,16 +4871,21 @@ msgid "" "at compile time. In this case the default implementations of `Copy` and " "`Clone` traits are generated." msgstr "" +"如果学员问起 `derive`,只需说这是一种\n" +"在编译时生成 Rust 代码的方法。在这种情况下,系统会生成 `Copy` 和 `Clone` " +"trait 的默认实现。" #: src/ownership/borrowing.md:1 msgid "# Borrowing" -msgstr "" +msgstr "# 借用" #: src/ownership/borrowing.md:3 msgid "" "Instead of transferring ownership when calling a function, you can let a\n" "function _borrow_ the value:" msgstr "" +"调用函数时,你可以让\n" +"函数“借用”值,而不是转移所有权:" #: src/ownership/borrowing.md:6 msgid "" @@ -4735,16 +4905,33 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" #: src/ownership/borrowing.md:22 msgid "" "* The `add` function _borrows_ two points and returns a new point.\n" "* The caller retains ownership of the inputs." msgstr "" +"* `add` 函数“借用”两个点并返回一个新点。\n" +"* 调用方会保留输入的所有权。" #: src/ownership/borrowing.md:27 msgid "Notes on stack returns:" -msgstr "" +msgstr "关于栈返回的说明:" #: src/ownership/borrowing.md:28 msgid "" @@ -4778,20 +4965,48 @@ msgid "" "all. If RVO did not happen, Rust will always performs a simple and efficient " "`memcpy` copy." msgstr "" +"* 证明从 `add` 返回的开销很低,因为编译器可以消除复制操作。更改上述代码以输出" +"栈地址,并在 [Playground] 上运行它。在“调试”优化级别中,地址应发生变化,而在" +"改成“发布”设置时保持不变:\n" +"\n" +" ```rust,editable\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +" }\n" +"\n" +" fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +" }\n" +" ```\n" +"* Rust 编译器能够执行返回值优化 (RVO)。\n" +"* 在 C++ 中,必须在语言规范中定义复制省略,因为构造函数可能会有附带效应。在 " +"Rust 中,这完全不是问题。如果 RVO 未发生,Rust 将始终执行简单且高效的 " +"`memcpy` 复制。" #: src/ownership/shared-unique-borrows.md:1 msgid "# Shared and Unique Borrows" -msgstr "" +msgstr "# 共享和唯一的借用" #: src/ownership/shared-unique-borrows.md:3 msgid "Rust puts constraints on the ways you can borrow values:" -msgstr "" +msgstr "Rust 限制了借用值的方式:" #: src/ownership/shared-unique-borrows.md:5 msgid "" "* You can have one or more `&T` values at any given time, _or_\n" "* You can have exactly one `&mut T` value." msgstr "" +"* 在任何给定时间,你都可以有一个或多个 `&T` 值,或者\n" +"* 你可以有且只有一个 `&mut T` 值。" #: src/ownership/shared-unique-borrows.md:8 msgid "" @@ -4810,6 +5025,20 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" #: src/ownership/shared-unique-borrows.md:25 msgid "" @@ -4821,14 +5050,19 @@ msgid "" "the new mutable borrow of `a` through `c`. This is a feature of the borrow " "checker called \"non-lexical lifetimes\"." msgstr "" +"* 上述代码无法编译,因为 `a` 同时作为可变值(通过 `c`)和不可变值(通过 `b`)" +"被借用。\n" +"* 将`b` 的 `println!` 语句移到引入 `c` 的作用域之前,这段代码就可以编译。\n" +"* 这样更改后,编译器会发现 `b` 只在通过 `c` 对 `a` 进行新可变借用之前使用过。" +"这是借用检查器的一个功能,名为“非词法作用域生命周期”。" #: src/ownership/lifetimes.md:1 msgid "# Lifetimes" -msgstr "" +msgstr "# 生命周期" #: src/ownership/lifetimes.md:3 msgid "A borrowed value has a _lifetime_:" -msgstr "" +msgstr "借用的值是有“生命周期”的:" #: src/ownership/lifetimes.md:5 msgid "" @@ -4850,13 +5084,13 @@ msgstr "" #: src/ownership/lifetimes-function-calls.md:1 msgid "# Lifetimes in Function Calls" -msgstr "" +msgstr "# 函数调用中的生命周期" #: src/ownership/lifetimes-function-calls.md:3 msgid "" "In addition to borrowing its arguments, a function can return a borrowed " "value:" -msgstr "" +msgstr "除了借用其参数之外,函数还可以返回借用的值:" #: src/ownership/lifetimes-function-calls.md:5 msgid "" @@ -4876,6 +5110,21 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" #: src/ownership/lifetimes-function-calls.md:21 msgid "" @@ -4885,6 +5134,11 @@ msgid "" " lifetime `a`\".\n" " * The _at least_ part is important when parameters are in different scopes." msgstr "" +"* `'a` 是一个泛型形参,由编译器推断出来。\n" +"* 以 `'` 和 `'a` 开头的生命周期是典型的默认名称。\n" +"* 将 `&'a Point` 读取为“借用的 `Point,至少\n" +"在 `a` 生命周期内有效。\n" +" * 当参数在不同的作用域时,“至少”部分至关重要。" #: src/ownership/lifetimes-function-calls.md:31 msgid "" @@ -4926,12 +5180,12 @@ msgstr "" #: src/ownership/lifetimes-data-structures.md:1 msgid "# Lifetimes in Data Structures" -msgstr "" +msgstr "# 数据结构中的生命周期" #: src/ownership/lifetimes-data-structures.md:3 msgid "" "If a data type stores borrowed data, it must be annotated with a lifetime:" -msgstr "" +msgstr "如果数据类型存储了借用的数据,则必须对其添加生命周期注释:" #: src/ownership/lifetimes-data-structures.md:5 msgid "" @@ -4954,6 +5208,24 @@ msgid "" "}\n" "```" msgstr "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog." +"\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" #: src/ownership/lifetimes-data-structures.md:25 msgid "" @@ -4971,6 +5243,16 @@ msgid "" "lifetime relationships between the references themselves, in addition to the " "lifetime of the struct itself. Those are very advanced use cases." msgstr "" +"* 在上述示例中,`Highlight` 注释会强制包含 `&str` 的底层数据的生命周期至少与" +"使用该数据的任何 `Highlight` 实例一样长。\n" +"* 如果 `text` 在 `fox`(或 `dog`)的生命周期结束前被消耗,借用检查器将抛出一" +"个错误。\n" +"* 借用数据的类型会迫使用户保留原始数据。这对于创建轻量级视图很有用,但通常会" +"使它们更难使用。\n" +"* 如有可能,让数据结构直接拥有自己的数据。\n" +"* 一些包含多个引用的结构可以有多个生命周期注释。除了结构体本身的生命周期之" +"外,如果需要描述引用之间的生命周期关系,则可能需要这样做。这些都是非常高级的" +"用例。" #: src/exercises/day-1/afternoon.md:1 msgid "# Day 1: Afternoon Exercises" @@ -20000,3 +20282,100 @@ msgstr "" " println!(\"You got: {:?}\", flip_coin());\n" "}\n" "```" + +#: src/ownership/lifetimes.md:5 +msgid "" +"* The lifetime can be implicit: `add(p1: &Point, p2: &Point) -> Point`.\n" +"* Lifetimes can also be explicit: `&'a Point`, `&'document str`.\n" +"* Read `&'a Point` as \"a borrowed `Point` which is valid for at least the\n" +" lifetime `a`\".\n" +"* Lifetimes are always inferred by the compiler: you cannot assign a " +"lifetime\n" +" yourself.\n" +" * Lifetime annotations create constraints; the compiler verifies that " +"there is\n" +" a valid solution.\n" +"* Lifetimes for function arguments and return values must be fully " +"specified,\n" +" but Rust allows these to be elided in most cases with [a few simple\n" +" rules](https://doc.rust-lang.org/nomicon/lifetime-elision.html)." +msgstr "" +"* 生命周期可以是隐式的:add(p1: &Point, p2: &Point) -> Point`。\n" +"* 生命周期也可以是显式的:`&'a Point`、`&'document str`。\n" +"* 将 `&'a Point` 读取为“一个借用的 `Point`,至少在\n" +"生命周期 `a` 内有效”。\n" +"* 生命周期始终由编译器推断出来:你不能自行\n" +"分配生命周期。\n" +" * 生命周期注释会创建约束条件;编译器会验证\n" +"是否存在有效的解决方案。\n" +"* 必须完全指定函数参数和返回值的生命周期,\n" +"但 Rust 允许在大多数情况下通过[一些简单的\n" +"规则](https://doc.rust-lang.org/nomicon/lifetime-elision.html)来省略此操作。" + +#: src/ownership/lifetimes-function-calls.md:31 +msgid "" +"* Move the declaration of `p2` and `p3` into a new scope (`{ ... }`), " +"resulting in the following code:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" Note how this does not compile since `p3` outlives `p2`.\n" +"\n" +"* Reset the workspace and change the function signature to `fn left_most<'a, " +"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear.\n" +"* Another way to explain it:\n" +" * Two references to two values are borrowed by a function and the function " +"returns\n" +" another reference.\n" +" * It must have come from one of those two inputs (or from a global " +"variable).\n" +" * Which one is it? The compiler needs to know, so at the call site the " +"returned reference is not used\n" +" for longer than a variable from where the reference came from." +msgstr "" +"* 将 `p2` 和 `p3` 的声明移至新作用域 (`{ ... }`),以产生以下代码:\n" +" ```rust,ignore\n" +" #[derive(Debug)]\n" +" struct Point(i32, i32);\n" +"\n" +" fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +" }\n" +"\n" +" fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +" }\n" +" ```\n" +" 请注意:由于 `p3` 的生命周期比 `p2` 长,因此无法编译。\n" +"\n" +"* 重置工作区,然后将函数签名更改为 `fn left_most<'a, 'b>(p1: &'a Point, p2: " +"&'a Point) -> &'b Point`。这不会被编译,因为 `'a` 和 `'b` 生命周期之间的关系" +"不明确。\n" +"* 另一种解释方式:\n" +" * 对两个值的两个引用被一个函数借用,该函数返回\n" +"另一个引用。\n" +" * 它必须是来自这两个输入中的一个(或来自一个全局变量)。\n" +" * 是哪一个呢?编译器需要知道这一点,因此在调用点,返回的引用\n" +"的使用时间不会超过引用的来源中的变量。"