[易学易懂系列|rustlang语言|零基础|快速入门|(4)]

· · 1023 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Borrowing

继续讲讲另一个重要的概念:借用(borrowing),

什么是借用?

我们先来看前一文章([易学易懂系列|rustlang语言|零基础|快速入门|(3)])的代码 :

let a = [1, 2, 3];

let b = a;

println!("{:?} {:?}", a, b);// [1, 2, 3] [1, 2, 3]

let a = vec![1, 2, 3];

let b = a;

println!("{:?} {:?}", a, b);// Error; use of moved value:a

我们从上篇文章知道,第二段代码会报错,那怎么才能不报错呢?

我们改成以下代码:

let a = vec![1, 2, 3];

let b =&a;//这里加了一个符号:&,表示借用

println!("{:?} {:?}", a, b);// correct

现在可以顺利通过傲娇的编程器女王的检查了!这就是“借用”的功效!

这里就出来一个rust语言的概念,叫借用(borrowing)。

来看下定义:

英语:Borrow (verb)To receive something with the promise of returning it.

翻译成中文:出来混,借了东西,迟早要还的!

那借用又分两类型:

1.共享借用(Shared Borrowing(&T))

数据可以借用给一个或多个用户(或线程),但只准一个用户修改。

2.可变借用(Mutable Borrowing(&mut T))

数据可以借用给一个用户,并只准这个用户修改,同时不准其他用户访问。

借用规则如下 :

1.数据同一时间,只能是其中一种借用,要么是共享借用(Shared Borrowing(&T)),要么是可变借用(Mutable Borrowing(&mut T))。

2.借用概念适用于复制类型(Copy type )和移动类型(Move type )。

请看如下代码:

fnmain() {

let muta=vec![1,2,3];

letb= &muta;//  &mut borrow of `a` starts here

//  ⁝

// some code     //  ⁝

// some code     //  ⁝

}//  &mut borrow of `a` ends here

fnmain() {

let muta=vec![1,2,3];

letb= &muta;//  &mut borrow of `a` starts here

// some code

println!("{:?}",a);// trying to access `a` as a shared borrow, so giving an error

}//  &mut borrow of `a` ends here

fnmain() {

let muta=vec![1,2,3];

{

letb= &muta;//  &mut borrow of `a` starts here

// any other code

}//  &mut borrow of `a` ends here

println!("{:?}",a);// allow borrowing `a` as a shared borrow

}

从上面代码,我们可以看出,借用,也是有“生命周期”的。

像这段代码 :

fn main() {let mut a = vec![1, 2, 3];let b = &mut a; // &mut borrow ofastarts here // some code

println!("{:?}", a); // trying to accessaas a shared borrow, so giving an error} // &mut borrow ofa ends here

为什么会报错?因为当最后一行代码:

println!("{:?}", a);

要访问a时,a对数据的所有权,已经借用给b了。a已经没有数据所有权。所以报错。

那要怎么办?

加上大括号“{}”。

如下 :

fnmain() {

let muta=vec![1,2,3];

{

letb= &muta;//  &mut borrow of `a` starts here

// any other code

}//  &mut borrow of `a` ends here

println!("{:?}",a);// allow borrowing `a` as a shared borrow

}

加上{}后,把借用,限定在大括号内,大括号结束后,b会把所有权还给a。

这时,a对数据有了所有权,就可以访问数据了!

那共享借用和可变借用有什么区别呢,请看代码如下 :

共享借用:

fnmain() {

leta= [1,2,3];

letb= &a;

println!("{:?} {}",a,b[0]);// [1, 2, 3] 1

}

fnmain() {

leta=vec![1,2,3];

letb=get_first_element(&a);

println!("{:?} {}",a,b);// [1, 2, 3] 1

}

fnget_first_element(a: &Vec)->i32 {

a[0]

}

第一段代码:

fn main() {let a = [1, 2, 3];let b = &a;println!("{:?} {}", a, b[0]); // [1, 2, 3] 1}

这里a借用给了b,为什么a还可以访问呢?因为a的类型是数组,是基本类型。这是复制类型,共享借用,只借用复制数据。所以,原来a还是拥有对原始数据的所有权。

第二段代码:

fn main() {let a = vec![1, 2, 3]; let b = get_first_element(&a);

println!("{:?} {}", a, b); // [1, 2, 3] 1

}

fn get_first_element(a: &Vec) -> i32 {a[0]}

这里定义一个函数,get_first_element,返回值为数组中的第一个值。b从函数中得到值1。没有什么问题。

现在我们修改一下函数get_first_element的代码,如下 :

fn get_first_element(a: &Vec) -> i32 {

a[0]=9;

a[0]

}

这时,傲娇的编译器女王,又扔出一个错误给你:

fn get_first_element(a: &Vec) -> i32 {| --------- help: consider changing this to be a mutable reference:&mut std::vec::Vec<i32>| a[0]=9;| ^ais a& reference, so the data it refers to cannot be borrowed as mutable

这些错误信息很清楚地告诉你:

你现在是共享借用,共享借用只能共享数据,不能修改!

那要修改怎么办?用可变借用啊!

把代码修改为如下就可以了:

fn main() {let mut a = vec![1, 2, 3]; let b = get_first_element(&mut a);

println!("{:?} {}", a, b); // [1, 2, 3] 1

}

fn get_first_element(a: &mut Vec) -> i32 { a[0]=9;

a[0]

}

可变借用:

fnmain() {

let muta= [1,2,3];

letb= &muta;

b[0]=4;

println!("{:?}",b);// [4, 2, 3]

}

fnmain() {

let muta= [1,2,3];

{

letb= &muta;

b[0]=4;

}

println!("{:?}",a);// [4, 2, 3]

}

fnmain() {

let muta=vec![1,2,3];

letb=change_and_get_first_element(&muta);

println!("{:?} {}",a,b);// [4, 2, 3] 4

}

fnchange_and_get_first_element(a: &mutVec)->i32 {

a[0]=4;

a[0]

}

以上,希望对你有用。

如果遇到什么问题,欢迎加入:rust新手群,在这里我可以提供一些简单的帮助,加微信:360369487,注明:博客园+rust

本人精通java高并发,DDD,微服务等技术实践,以及python,golang技术栈。

本人精通java高并发,DDD,微服务等技术实践,以及python,golang技术栈。

本人名字郭莹城,坐标深圳,前IBM架构师、咨询师、敏捷开发技术教练,前IBM区块链研究小组成员、多年架构设计工作经验,《区块链核心技术与应用》作者之一,

现有成熟团队提供区块链开发相关业务(公链,交易所,钱包,Dapp,智能合约)。

工作微信&QQ:360369487,交易所开发与区块链钱包开发业务,加我注明:博客园+开发,想学习golang和rust的同学,也可以加我微信,备注:博客园+golang或博客园+rust,谢谢!

原文:https://www.cnblogs.com/gyc567/p/11910563.html


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:

查看原文:[易学易懂系列|rustlang语言|零基础|快速入门|(4)]

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1023 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传