阅读量:0
练习题来自:https://practice-zh.course.rs/ownership/ownership.html
1
fn main() { // 使用尽可能多的方法来通过编译 let x = String::from("hello, world"); let y = x; println!("{},{}",x,y); }
这是最典型的所有权转移的错误,x拥有字符串的所有权,然后转给了y,此时x不再拥有所有权了。以下给出两种方法:
1
可以对字符串执行一次克隆clone:
fn main() { // 使用尽可能多的方法来通过编译 let x = String::from("hello, world"); let y = x.clone(); println!("{},{}",x,y); }
2
让x作为引用,而不是所有者,但是就不能用string了,得用str:
fn main() { // 使用尽可能多的方法来通过编译 let x: &str = "hello, world"; let y = x; println!("{},{}",x,y); }
3
// 不要修改 main 中的代码 fn main() { let s1 = String::from("hello, world"); let s2 = take_ownership(s1); println!("{}", s2); } // 只能修改下面的代码! fn take_ownership(s: String) { println!("{}", s); }
一个很简单的所有权转移:
// 不要修改 main 中的代码 fn main() { let s1 = String::from("hello, world"); let s2 = take_ownership(s1); println!("{}", s2); } // 只能修改下面的代码! fn take_ownership(s: String) -> String { println!("{}", s); return s; }
4
// 修复错误,不要删除任何代码行 fn main() { let s = String::from("hello, world"); print_str(s); println!("{}", s); } fn print_str(s: String) { println!("{}",s) }
s的所有权在print_str中转移了,函数结束后就丢失了,因此此处改为借用即可:
fn main() { let s = String::from("hello, world"); print_str(&s); println!("{}", s); } fn print_str(s: &String) { println!("{}",s) }
5
// 不要使用 clone,使用 copy 的方式替代 fn main() { let x = (1, 2, (), "hello".to_string()); let y = x.clone(); println!("{:?}, {:?}", x, y); }
唯一问题在于string不是基本类型,因此去掉to_string即可,改为&str
fn main() { let x = (1, 2, (), "hello"); let y = x; println!("{:?}, {:?}", x, y); }
6
fn main() { let x = Box::new(5); let ... // 完成该行代码,不要修改其它行! *y = 4; assert_eq!(*x, 5); }
不知道这个Box类存在的意义是什么(我也懒得去查),这题的目的明显是想让y成为一个针对数字类型的可变引用,这么改就行:
fn main() { let x = Box::new(5); let y = &mut 5; // 完成该行代码,不要修改其它行! *y = 4; assert_eq!(*x, 5); }
7
fn main() { let s = String::from("hello, "); // 只修改下面这行代码 ! let s1 = s; s1.push_str("world") }
第一种方法就是克隆一份s变量:
fn main() { let s = String::from("hello, "); // 只修改下面这行代码 ! let mut s1 = s.clone(); s1.push_str("world") }
第二种直接修改s,但要修改s为可变变量,不如第一种破坏小(但没准更接近作者本意):
fn main() { let mut s = String::from("hello, "); // 只修改下面这行代码 ! let s1 = &mut s; s1.push_str("world") }
8
fn main() { let t = (String::from("hello"), String::from("world")); let _s = t.0; // 仅修改下面这行代码,且不要使用 `_s` println!("{:?}", t); }
t的第一部分的所有权转移给了_s,但是第二部分还是没有转移的,所以可以修改如下:
fn main() { let t = (String::from("hello"), String::from("world")); let _s = t.0; // 仅修改下面这行代码,且不要使用 `_s` println!("{}", t.1); }
9
fn main() { let t = (String::from("hello"), String::from("world")); // 填空,不要修改其它代码 let (__, __) = __; println!("{:?}, {:?}, {:?}", s1, s2, t); // -> "hello", "world", ("hello", "world") }
同上,改为引用即可:
fn main() { let t = (String::from("hello"), String::from("world")); // 填空,不要修改其它代码 let (s1, s2) = &t; println!("{:?}, {:?}, {:?}", s1, s2, t); // -> "hello", "world", ("hello", "world") }