Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ownership/borrowing #373

giscus[bot] bot announced in Book Comments
Feb 27, 2023 · 69 comments · 18 replies
Discussion options

ownership/borrowing

Learning Rust By Practice, narrowing the gap between beginner and skilled-dev with challenging examples, exercises and projects.

https://zh.practice.rs/ownership/borrowing.html

You must be logged in to vote

Replies: 69 comments 18 replies

Comment options

mark

You must be logged in to vote
0 replies
Comment options

逐渐开始硬核起来了,烧脑

You must be logged in to vote
0 replies
Comment options

done! lala~

You must be logged in to vote
0 replies
Comment options

第6题,哪里tm讲了ref

You must be logged in to vote
4 replies
Comment options

推理猜一下(doge

Comment options

5.1所有权习题里面提了一个部分Move。其中的示例用到了ref

Comment options

你已经是一个成熟的程序员了,是时候自己猜了

Comment options

前面几章的习题也有很多这种没讲的东西

Comment options

新编译器作用域在最后一次使用的位置 所以第10题 最后一句可以把r1改成r2 🥳

You must be logged in to vote
1 reply
Comment options

我特意用1.70的编译器试了一遍,还真是

Comment options

这个第10题一下还真没想到

You must be logged in to vote
0 replies
Comment options

题出的都很好

You must be logged in to vote
0 replies
Comment options

打卡感謝課後練習 這樣才有學到的感覺

You must be logged in to vote
0 replies
Comment options

打卡!

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Comment options

done!

You must be logged in to vote
0 replies
Comment options

不符合题目的一些内容
7

// 移除代码某个部分,让它工作
// 你不能移除整行的代码!
fn main() {
 let mut s = String::from("hello");
 let r1 = &mut s;
 let r2 = &r1;
 println!("{}, {}", r1, r2);
}

10

// 注释掉一行代码让它工作
fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 r1.push_str("world");
 //r2.push_str("!");
 
 println!("{}",r1);
 let r2 = &mut s;
}
You must be logged in to vote
1 reply
Comment options

两个题目都是没问题的,你可以仔细看下:

7-不可变引用可以存在多个

// 移除代码某个部分,让它工作
// 你不能移除整行的代码!
fn main() {
 let mut s = String::from("hello");
 let r1 = &s;
 let r2 = &s;
 println!("{}, {}", r1, r2);
}

10- 移除最后一行打印的代码,会让r1的作用域仅仅到r1.push就结束了,不违反某一作用域内同时存在多个可变引用。

// 注释掉一行代码让它工作
fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 r1.push_str("world");
 let r2 = &mut s;
 r2.push_str("!");
 
 // println!("{}",r1);
}
Comment options

1、第一题,引用的值

Q:

fn main() {
 let x = 5;
 // 填写空白处
 let p = __;
 println!("x 的内存地址是 {:p}", p); // output: 0x16fa3c84
}

A:

fn main() {
 let x = 5;
 let p = &x;//获取指向x的地址
 println!("x 的内存地址是 {:p}", p); // output: 0x16fa3ac84
}

2、第二题,如何解引用

Q:

fn main() {
 let x = 5;
 let y = &x;
 // 只能修改以下行
 assert_eq!(5, y);
}

A:

fn main() {
 let x = 5;
 let y = &x;
 // 只能修改以下行
 assert_eq!(5, *y);//解引用获取引用y指向地址的值,也就是x
}

3、第三题,修复错误

Q:

// 修复错误
fn main() {
 let mut s = String::from("hello, ");
 borrow_object(s)
}
fn borrow_object(s: &String) {}

A:

fn main() {
 let mut s = String::from("hello, ");
 borrow_object(&s)//只需要求改这里即可
}
fn borrow_object(s: &String) {}//其实题干已经提示了,在这里要传入的是一个引用,引用不触发所有权矛盾

4、第四题,可变引用

Q:

// 修复错误
fn main() {
 let mut s = String::from("hello, ");
 push_str(s)
}
fn push_str(s: &mut String) {
 s.push_str("world")
}

A:

fn main() {
 let mut s = String::from("hello, ");
 push_str(& mut s)//可以从函数调用中传参的类型来推理此处变量类型
}
fn push_str(s: &mut String) {
 s.push_str("world")
}

5、第五题

Q:

fn main() {
 let mut s = String::from("hello, ");
 // 填写空白处,让代码工作
 let p = __;
 
 p.push_str("world");
}

A:

fn main() {
 let mut s = String::from("hello, ");
 // 填写空白处,让代码工作
 let p = &mut s;//p传入的是指向s的地址,且因为下面有要求修改值,所以借用不够,还需要声明可变mut
 
 p.push_str("world");
}

结合上一节内容,考虑这里写成深度拷贝,但是如此以来修改部分就不止__部分,还需要声明p为mut可变才行,严格意义上不算正确答案([狗头].jpg)

fn main() {
 let mut s = String::from("hello, ");
 let mut p = s.clone();
 
 p.push_str("world");
}

6、第六题,ref和&

Q:

fn main() {
 let c = '中';
 let r1 = &c;
 // 填写空白处,但是不要修改其它行的代码
 let __ r2 = c;
 assert_eq!(*r1, *r2);
 
 // 判断两个内存地址的字符串是否相等
 assert_eq!(get_addr(r1),get_addr(r2));
}
// 获取传入引用的内存地址的字符串形式
fn get_addr(r: &char) -> String {
 format!("{:p}", r)
}

A:

fn main() {
 let c = '中';
 let r1 = &c;
 // 我浅薄理解为:ref在左边使用,&在右边使用
 let ref r2 = c;
 assert_eq!(*r1, *r2);
 
 // 判断两个内存地址的字符串是否相等
 assert_eq!(get_addr(r1),get_addr(r2));
}
// 获取传入引用的内存地址的字符串形式
fn get_addr(r: &char) -> String {
 format!("{:p}", r)
}

7、第七题,可变引用以及多个引用

Q:

// 移除代码某个部分,让它工作
// 你不能移除整行的代码!
fn main() {
 let mut s = String::from("hello");
 let r1 = &mut s;
 let r2 = &mut s;
 println!("{}, {}", r1, r2);
}

A:

fn main() {
 let mut s = String::from("hello");
//一个域里面有一个可变引用后就无法使用其他引用,所以mut必须都去掉
 let r1 = & s;
 let r2 = & s;
 println!("{}, {}", r1, r2);
}

8、第八题,从不可变对象中借用可变

Q:

fn main() {
 // 通过修改下面一行代码来修复错误
 let s = String::from("hello, ");
 borrow_object(&mut s)
}
fn borrow_object(s: &mut String) {}

A:

fn main() {
 // String属于不可变对象?又学到了,然后mut自然就不可以用了
 let s = String::from("hello, ");
 borrow_object(& s)
}
fn borrow_object(s: & String) {}

10、第十题

Q:

// 注释掉一行代码让它工作
fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 r1.push_str("world");
 let r2 = &mut s;
 r2.push_str("!");
 
 println!("{}",r1);
}

A:

// 注释掉一行代码让它工作
fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 r1.push_str("world");//调用完这个函数之后,r1就被释放掉了
 let r2 = &mut s;
 r2.push_str("!");
 
 //println!("{}",r1);
}

11、第十一题

Q:

fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 let r2 = &mut s;
	
 // 在下面增加一行代码人为制造编译错误:cannot borrow `s` as mutable more than once at a time
 // 你不能同时使用 r1 和 r2
}

A:

fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 let r2 = &mut s;
	r1.push_str("world");//因为一次只有一个可变引用可以改值,所以添加这个编译器就会报错(好家伙,我以为不添加这一行的话按照我的理解也会报错,原来还是需要尝试通过引用改变来触发这个编译error)
}
You must be logged in to vote
4 replies
Comment options

第十题 r1在调用函数后并没有释放,不然你在下一句重新再用r1调用试试。因为又绑定了r2为s的可变引用,所以r1才被释放的。

Comment options

不是,是因为nll发现r1在r2声明之前就不再使用了,所以编译器直接drop了r1

Comment options

是你,破墙侠!!!!,我老是访问不到gitup!!!

Comment options

第5题如果不按划线的话,也可以写成

fn main() {
 let mut s = String::from("hello, ");
 let mut p = s;
 
 p.push_str("world");
}

fn main() {
 let mut s = String::from("hello, ");
 let ref mut p = s;
 
 p.push_str("world");
}
Comment options

前面的教程中好像没有对ref的介绍

You must be logged in to vote
0 replies
Comment options

Done!

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Comment options

Done

You must be logged in to vote
0 replies
Comment options

Done

You must be logged in to vote
0 replies
Comment options

为啥输出这两个值一样的

fn main() {
 let x = 5;
 let p = &x;
 
 println!("{}",*p );
 println!("{}", p );
 
 }
You must be logged in to vote
2 replies
Comment options

有同样的疑问。请高人回答!

Comment options

用println!("{:p}", p );打印指针指向的地址

Comment options

day2 完成所有权部分

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Comment options

第10题其实是注释掉println!("{}",r1);

// 注释掉一行代码让它工作
fn main() {
 let mut s = String::from("hello, ");
 let r1 = &mut s;
 r1.push_str("world");
 let r2 = &mut s;
 r2.push_str("!");
 
 // println!("{}",r1);
}
You must be logged in to vote
1 reply
Comment options

因为 r1 是一个可变引用,当我们创建 r2 时, r1 的生命周期应该已经结束了

Comment options

为什么我题目显示不全

You must be logged in to vote
0 replies
Comment options

第10个放生命周期比较好

You must be logged in to vote
0 replies
Comment options

标记完成

You must be logged in to vote
0 replies
Comment options

yooo

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Comment options

done

You must be logged in to vote
0 replies
Comment options

最后一行只能看到一半,浏览器是firefox的发行版,zen浏览器。

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /