diff --git a/en/src/ownership/ownership.md b/en/src/ownership/ownership.md index 33f9384..d9b6252 100644 --- a/en/src/ownership/ownership.md +++ b/en/src/ownership/ownership.md @@ -1,6 +1,6 @@ # Ownership -🌟🌟 +🌟🌟 ```rust,editable fn main() { @@ -71,3 +71,93 @@ fn main() { } ``` +#### Mutability +Mutability can be changed when ownership is transferred. + +🌟 +```rust,editable + +fn main() { + let s = String::from("hello, "); + + // modify this line only ! + let s1 = s; + + s1.push_str("world") +} +``` + +🌟🌟🌟 +```rust,editable + +fn main() { + let x = Box::new(5); + + let ... // implement this line, dont change other lines! + + *y = 4; + + assert_eq!(*x, 5); +} +``` + +### Partial move +Within the destructuring of a single variable, both by-move and by-reference pattern bindings can be used at the same time. Doing this will result in a partial move of the variable, which means that parts of the variable will be moved while other parts stay. In such a case, the parent variable cannot be used afterwards as a whole, however the parts that are only referenced (and not moved) can still be used. + +#### Example +```rust,editable + +fn main() { + #[derive(Debug)] + struct Person { + name: String, + age: Box, + } + + let person = Person { + name: String::from("Alice"), + age: Box::new(20), + }; + + // `name` is moved out of person, but `age` is referenced + let Person { name, ref age } = person; + + println!("The person's age is {}", age); + + println!("The person's name is {}", name); + + // Error! borrow of partially moved value: `person` partial move occurs + //println!("The person struct is {:?}", person); + + // `person` cannot be used but `person.age` can be used as it is not moved + println!("The person's age from person struct is {}", person.age); +} +``` + +#### Exercises + +🌟 +```rust,editable + +fn main() { + let t = (String::from("hello"), String::from("world")); + + let _s = t.0; + + // modify this line only, don't use `_s` + println!("{:?}", t); +} +``` + +🌟🌟 +```rust,editable + +fn main() { + let t = (String::from("hello"), String::from("world")); + + // fill the blanks + let (__, __) = t; + + println!("{:?}, {:?}, {:?}", s1, s2, t); +} +``` diff --git a/zh-CN/src/SUMMARY.md b/zh-CN/src/SUMMARY.md index af7f561..bf84423 100644 --- a/zh-CN/src/SUMMARY.md +++ b/zh-CN/src/SUMMARY.md @@ -7,7 +7,7 @@ - [字符、布尔、单元类型](basic-types/char-bool-unit.md) - [语句与表达式](basic-types/statements-expressions.md) - [函数](basic-types/functions.md) -- [所有权和借用 todo](ownership/intro.md) +- [所有权和借用](ownership/intro.md) - [所有权](ownership/ownership.md) - [引用和借用](ownership/borrowing.md) - [复合类型 todo](compound-types/intro.md) diff --git a/zh-CN/src/ownership/ownership.md b/zh-CN/src/ownership/ownership.md index b429a6b..2e506ca 100644 --- a/zh-CN/src/ownership/ownership.md +++ b/zh-CN/src/ownership/ownership.md @@ -72,3 +72,96 @@ fn main() { } ``` +#### 可变性 +当所有权转移时,可变性也可以随之改变。 + +🌟 +```rust,editable + +fn main() { + let s = String::from("hello, "); + + // 只修改下面这行代码 ! + let s1 = s; + + s1.push_str("world") +} +``` + +🌟🌟🌟 +```rust,editable + +fn main() { + let x = Box::new(5); + + let ... // 完成该行代码,不要修改其它行! + + *y = 4; + + assert_eq!(*x, 5); +} +``` + +### 部分 move +当解构一个变量时,可以同时使用 `move` 和引用模式绑定的方式。当这么做时,部分 `move` 就会发生:变量中一部分的所有权被转移给其它变量,而另一部分我们获取了它的引用。 + +在这种情况下,原变量将无法再被使用,但是它没有转移所有权的那一部分依然可以使用,也就是之前被引用的那部分。 + +#### 示例 +```rust,editable + +fn main() { + #[derive(Debug)] + struct Person { + name: String, + age: Box, + } + + let person = Person { + name: String::from("Alice"), + age: Box::new(20), + }; + + // 通过这种解构式模式匹配,person.name 的所有权被转移给新的变量 `name` + // 但是,这里 `age` 变量确是对 person.age 的引用, 这里 ref 的使用相当于: let age = &person.age + let Person { name, ref age } = person; + + println!("The person's age is {}", age); + + println!("The person's name is {}", name); + + // Error! 原因是 person 的一部分已经被转移了所有权,因此我们无法再使用它 + //println!("The person struct is {:?}", person); + + // 虽然 `person` 作为一个整体无法再被使用,但是 `person.age` 依然可以使用 + println!("The person's age from person struct is {}", person.age); +} +``` + +#### 练习 + +🌟 +```rust,editable + +fn main() { + let t = (String::from("hello"), String::from("world")); + + let _s = t.0; + + // 仅修改下面这行代码,且不要使用 `_s` + println!("{:?}", t); +} +``` + +🌟🌟 +```rust,editable + +fn main() { + let t = (String::from("hello"), String::from("world")); + + // 填空,不要修改其它代码 + let (__, __) = t; + + println!("{:?}, {:?}, {:?}", s1, s2, t); +} +``` \ No newline at end of file