【Rust练习】7.引用与借用

35 篇文章 0 订阅
13 篇文章 0 订阅

练习题来自:https://practice-zh.course.rs/ownership/borrowing.html

1

fn main() {
   let x = 5;
   // 填写空白处
   let p = __;

   println!("x 的内存地址是 {:p}", p); // output: 0x16fa3ac84
}

其实Rust的借用,就类似C++的指针和引用,如果你有C++的基础,这道题就很好理解——取p的地址。

fn main() {
    let x = 5;
    // 填写空白处
    let p = &x;

    println!("x 的内存地址是 {:p}", p); // output: 0x16fa3ac84
}

运行结果

2

fn main() {
    let x = 5;
    let y = &x;

    // 只能修改以下行
    assert_eq!(5, y);
}

对熟悉C++的同学来说,这道题也很好理解,&用于取地址,而*用于从地址取数据。

fn main() {
    let x = 5;
    let y = &x;

    // 只能修改以下行
    assert_eq!(5, *y);
}

3

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

    borrow_object(s)
}

fn borrow_object(s: &String) {}

函数入参应该是String的借用(指针),而不是String本身。

fn main() {
    let mut s = String::from("hello, ");

    borrow_object(&s)
}

fn borrow_object(s: &String) {}

4

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

    push_str(s)
}

fn push_str(s: &mut String) {
    s.push_str("world")
}

和上面一样,不多解释了。

fn main() {
    let mut s = String::from("hello, ");

    push_str(&mut s)
}

fn push_str(s: &mut String) {
    s.push_str("world")
}

5

fn main() {
    let mut s = String::from("hello, ");

    // 填写空白处,让代码工作
    let p = __;
    
    p.push_str("world");
}

应该是对s的可变引用。

fn main() {
    let mut s = String::from("hello, ");

    // 填写空白处,让代码工作
    let p = &mut s;

    p.push_str("world");
}

6

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)
}

ref x = p,就是x = &p

fn main() {
    let c = '中';

    let r1 = &c;
    // 填写空白处,但是不要修改其它行的代码
    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

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

    let r1 = &mut s;
    let r2 = &mut s;

    println!("{}, {}", r1, r2);
}

可变引用同时只能存在一个,因此都改成不可变即可(这样变量的mut就没意义了)。

fn main() {
    let mut s = String::from("hello");

    let r1 = & s;
    let r2 = & s;

    println!("{}, {}", r1, r2);
}

8

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

    borrow_object(&mut s)
}

fn borrow_object(s: &mut String) {}

类似于C++里对变量声明const和指针的关系一样(现在应该用constexpr了)。常量只能使用常量指针,比如如下代码:

const int num = 1;

使用如下指针是不能指向num的:

int *const p = #//p不可被更改,但p指向的数据,也就是num可以更改。这和num是const矛盾。此行代码会编译失败。

正确的写法是:

int const *p = #//虽然p本身可以被修改(比如可以指向别的数据),但p所指向的数据不可更改。

C++中的引用类似,只不过引用本身不是对象,所以没有改变这个概念,const 引用才能引用常量。
Rust也一样,s不可变,那就不能有任何一个可变的引用借用s

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

    borrow_object(&mut s)
}

fn borrow_object(s: &mut String) {}

9

// 下面的代码没有任何错误
fn main() {
    let mut s = String::from("hello, ");

    borrow_object(&s);
    
    s.push_str("world");
}

fn borrow_object(s: &String) {}

同上,不可变的引用指向可变的变量是可以的,但是这个引用不能拿来改变变量(即使变量可变)

10

// 注释掉一行代码让它工作
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);
}

r1作为引用的作用域直到自身最后一次出现为止,因此,r2刚好在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);
}

11

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
}

同上。

fn main() {
    let mut s = String::from("hello, ");

    let r1 = &mut s;
    let r2 = &mut s;

    r1.push_str("string");

    // 在下面增加一行代码人为制造编译错误:cannot borrow `s` as mutable more than once at a time
    // 你不能同时使用 r1 和 r2
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值