博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Rust基础笔记之浅谈Ownership
阅读量:6097 次
发布时间:2019-06-20

本文共 2205 字,大约阅读时间需要 7 分钟。

hot3.png

写在前面

Ownership System是Rust中最独特和吸引人的特性,Rust也是依靠这个特性来实现他的最大的目标:内存安全,所有Rust的开发者都应该详细了解它。

多么浓厚的翻译味道,的确本人学习Rust主要依靠官方的文档(写的很清楚详细),这个系列的文章是我学习Rust的笔记,不完全是翻译官方文档,但大部分内容都是来源于官方文档,但是加上了很多自己的理解、思考和总结,这些笔记呢也都是最基本的概念,暂时并没有深入研究,希望大家在阅读文章的时候能多去看看官方手册,欢迎批评指正和补充。

Ownership(所有权)

Rust有一个非常棒的特点,那就是能在编译的时候检查出大多数安全隐患,这就避免了像C语言一样,编译一切OK,运行时来个Segment Fault,让人不明所以,所以Rust需要一套机制来保证在编译时期发现这些问题,这就是强大的Ownership System,它呢,包含了三个部分:

  • Ownership

  • Borrowing

  • Lifetime

(后面都会说到),这玩意确实不怎么好理解,得慢慢来。


当声明一个变量绑定的时候,即该变量拥有了对应内存区域的所有权,当该变量超出作用域的时候,它所指向的内存就会被释放。

当然,我们可以将它指派给其他的绑定,就像这样:

//the vector allocates space on the heaplet v=vec![1, 2, 3];let v2=v;

如果在新的绑定之后调用原先的变量,就会得到如下错误:

error: use of moved value: `v`

原因是let v2 = v;该语句将v所指向的内存区域移交给(move)了v2,之所以报错,官方文档的原话是:

When we move v to v2, it creates a copy of that pointer, for v2. Which means that there would be two pointers to the content of the vector on the heap. It would violate Rust's safety guarantees by introducing a data race. Therefore, Rust forbids using v after we’ve done the move.

意思就是说,现在有两个指针指向了该内存区域,为了避免数据竞争,Rust是不允许使用move后的源变量。

这里有一个问题就是:如果v2超出了它的作用域之后,还能调用v吗?

let v = vec![1,2,3];    {    let v2 = v;}println!("v[0] is {} ",v[0]);

结果是依然报错:

error: use of moved value: `v`

也就是说当v2超出其作用域后,v2并不会归还其对应的内存区域的所有权。

对于函数而言也会遇到一样的问题:

fn take(v: Vec
) {    // what happens here isn’t important.}let v = vec![1, 2, 3];take(v);println!("v[0] is: {}", v[0]);

依然会遇到这样的问题

error: use of moved value: `v`

你可能会觉得好像有的变量绑定就不是这样的,比如:

let v = 1;let v2 = v;println!("v is {}",v);println!("v2 is {}",v2);

这段代码就可以正常输出啊。

这是因为x是i32类型的,它实现了Copy的特性,官方文档的原话是:

In this case, v is an i32, which implements the Copy trait. This means that, just like a move, when we assign v to v2, a copy of the data is made. But, unlike a move, we can still use v afterward. This is because an i32 has no pointers to data somewhere else, copying it is a full copy.

之所以上面的代码没有问题,是因为它是一个完全拷贝,连同数据也复制了一份,不存在两个指针指向同一块内存区域的问题,更谈不上数据竞争,所以这段代码并没有Rust的安全机制,自然也就是允许的,这是和move不同的地方。

如果你想在v2之后还想使用v,可以用如下的方式:

let v = vec![1,2,3];    let v2 = v;println!("y[0] is {} ",y[0]);let v = v2; //交回所有权println!("v[0] is {} ",v[0]);

这样的语法是不是很麻烦,有没有办法让v2再超出作用域后自己交回所有权呢?有来看看Borrow的概念吧。

转载于:https://my.oschina.net/cppblog/blog/638818

你可能感兴趣的文章
dubbo
查看>>
【Git入门之四】操作项目
查看>>
老男孩教育每日一题-第107天-简述你对***的理解,常见的有哪几种?
查看>>
Python学习--time
查看>>
在OSCHINA上的第一篇博文,以后好好学习吧
查看>>
高利率时代的结局,任重道远,前途叵测
查看>>
Debian 6.05安装后乱码
查看>>
欢迎大家观看本人录制的51CTO精彩视频课程!
查看>>
IntelliJ IDEA中设置忽略@param注释中的参数与方法中的参数列表不一致的检查
查看>>
关于软件开发的一些感悟
查看>>
uva 10806
查看>>
纯CSS3绘制的黑色图标按钮组合
查看>>
Linux中环境变量文件及配置
查看>>
从0开始学Flutter
查看>>
mysql操作入门基础之对数据库和表的增删改查
查看>>
IIS负载均衡
查看>>
分布式事务,EventBus 解决方案:CAP【中文文档】
查看>>
Linux下的CPU性能瓶颈分析案例
查看>>
spring mvc入门
查看>>
2012在数据库技术会议上的讲话PPT打包
查看>>