博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
rust所有权理解(备忘)
阅读量:4224 次
发布时间:2019-05-26

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

    最近闲的没事,就准备学习一下rust。
rust是Mozilla开发的一门编程语言。
rust是为了多核系统而设计的一门编程语言,它因其特殊的机制有线程安全性,编译期查出内存错误的优点,可能语法有着那么点另类,但我想这不是问题。至于它和另外一门编程语言GO的优缺点,请自行了解,因为我也是小白,并不敢发表什么高见。
本文只是用自己的语言再次理解了一些rust的所有权机制,官方的文档应该比我更加详尽。有兴趣的可以去看看,
地址: https://www.rust-lang.org/zh-CN/
正如上文所说,rust有编译期查错的能力以及线程安全的能力,这就是rust的特有机制,所有权机制。
首先我们先看一下所有权机制的规则(摘自官方文档):
1.Rust 中的每一个值都有一个叫做它的所有者(owner)的变量。     2.同时一次只能有一个所有者     3.当所有者变量离开作用域,这个值将被丢弃。
         我们接下来会用代码的形式来进行讲解,不懂的可以去官方文档看看语法。
首先我们看一段代码
{        let x = String::from("test");        println!("in scope hello this is {}", x);    }    println!("out scope hello this is {}", x);
         当然,这段代码是无法执行的,因为根本无法通过编译,报错如下
error[E0425]: cannot find value `x` in this scope  --> src/main.rs:13:40   |13 | println!("out scope hello this is {}", x);   |                                        ^ not found in this scope
  因为x在为这个String的值的所有者,在所有者离开作用域后值直接被释放了,这一点和其它编程语言是很相似的。
接下来我们看这一段代码
let x = String::from("123");     let y = x;     println!("x = {}, y = {}", x, y);
你们可能此时也已经在猜测运行结果了,很遗憾,这段代码也是无法运行的
报错为:
error[E0382]: use of moved value: `x`  --> src/main.rs:11:32   |10 |     let y = x;   |         - value moved here11 |     println!("x = {}, y = {}", x, y);   |                                ^ value used here after move   |   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
 报错上显示x的值被移动了,你们可能在想,这是什么鬼。我们接下来就来扯一下数据的内存吧
实际上x是所有者,指向了堆上的一块内存,因为在rust中,非基本数据类型都是存储在堆上的,其它语言基本也是这样的。而let x = String::from("123");这个语言实际上是将x指向了那块内存。而let y = x则是将y指向了与x指向内存相同的那块内存。在其它语言中也是这样的,因为复制堆上的数据对运行效率影响很大。如果你们有其它语言的基础,那么这个过程其实就是浅拷贝,同时你们也应该了解这样会导致什么错误的出现,即任何该值的所有者均可对这块内存进行修改甚至删除,而rust解决了这个问题,rust使第一个变量,即x无效化了,这样就不会出现上述的问题了,这个就是数据的移动,是不是很形象。
那么我们再看另外一段代码:
let x = 1;     let y = x;     println!("x = {}, y = {}", x, y);
是不是觉得这段代码也不能执行,这就错了,这段代码可以正常执行,并且运行结果如你所想。因为在rust中,基本数据类型是存储这栈上的,而对栈的拷贝操作对运行效率的影响是微乎其微的,所以对栈上数据的引用都是默认是拷贝的。所以对于上一段代码其实也是可以对x进行深拷贝从而让它成功运行的。但是这样正如前面所说的,会影响运行效率。所以rust为了兼顾运行效率和安全,它使用了无效化这个方法。当然这个方法也会导致相应的问题,例如:
fn hello(str: String)    {        println!("{}", str);    }    fn test()    {        let x = String::from("123");        hello(x);        println!("x = {}", x);    }
这个会编译失败,报错为
error[E0382]: use of moved value: `x`  --> src/main.rs:15:24   |14 |     hello(x);   |           - value moved here15 |     println!("x = {}", x);   |                        ^ value used here after move   |   = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
因为x的值已经被转移到了hello函数的str参数中了,所以x无效化了,故而会导致这个错误。这个问题我们当然可以通过让hello函数返回x的值来解决,但是这个解决办法略显蛋疼,而且rust已经为我们解决了更好的方案了,具体的我们下篇文章再讲,如果我记得写的话(笑:-D),当然你们也可以去看rust的文档。习惯了以rust的所有权系统来编程,你在编写其它编程语言的时候也能写成更加安全的代码
String in memory

转载地址:http://yigmi.baihongyu.com/

你可能感兴趣的文章
CSS之浮动(二)
查看>>
AtomicInteger源码解析
查看>>
CopyOnWriteArraySet源码学习
查看>>
Openfiler 配置 NFS 示例
查看>>
Oracle 11.2.0.1 RAC GRID 无法启动 : Oracle High Availability Services startup failed
查看>>
Oracle 18c 单实例安装手册 详细截图版
查看>>
Oracle Linux 6.1 + Oracle 11.2.0.1 RAC + RAW 安装文档
查看>>
Oracle 11g 新特性 -- Online Patching (Hot Patching 热补丁)说明
查看>>
Oracle 11g 新特性 -- ASM 增强 说明
查看>>
Oracle 11g 新特性 -- Database Replay (重演) 说明
查看>>
Oracle 11g 新特性 -- 自动诊断资料档案库(ADR) 说明
查看>>
CSDN博客之星 投票说明
查看>>
Oracle wallet 配置 说明
查看>>
Oracle smon_scn_time 表 说明
查看>>
VBox fdisk 不显示 添加的硬盘 解决方法
查看>>
Secure CRT 自动记录日志 配置 小记
查看>>
RMAN RAC 到 单实例 duplicate 自动分配通道 触发 ORA-19505 错误
查看>>
mysql 随机分页的优化
查看>>
DB2快速创建测试库
查看>>
SD卡驱动分析--基于高通平台
查看>>