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