练习题来自:https://practice-zh.course.rs/ownership/ownership.html
fn main() { // 使用尽可能多的方法来通过编译 let x = String::from("hello, world"); let y = x; println!("{},{}",x,y); } 这是最典型的所有权转移的错误,x拥有字符串的所有权,然后转给了y,此时x不再拥有所有权了。以下给出两种方法:
可以对字符串执行一次克隆clone:
fn main() { // 使用尽可能多的方法来通过编译 let x = String::from("hello, world"); let y = x.clone(); println!("{},{}",x,y); } 让x作为引用,而不是所有者,但是就不能用string了,得用str:
fn main() { // 使用尽可能多的方法来通过编译 let x: &str = "hello, world"; let y = x; println!("{},{}",x,y); } // 不要修改 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; } // 修复错误,不要删除任何代码行 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) } // 不要使用 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); } 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); } 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") } 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); } 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") }