Rust中文翻译13

翻译 2015年07月06日 23:33:00
 目前为止,这机制工作的不错.但是不是所有的事情都是这样的.有时,你需要在不同的函数中传递内存数据,或者你需要把内存数据的生命期拉长到一个函数范围之外.为此,我们可以用堆.

在Rust语言中,你可以试用Box<T>类型来分配堆上的内存空间.这有个例子:
fn main() {
    let x = Box::new(5);
    let y = 42;
}

当main()函数调用的时候,内存是这样的:
地址 名字
1 y 42
0 x ???

我们在栈上分配了2个变量.y是42,正如以往的一样,那么x又是什么呢?x是一个Box<i32>,boxes是在堆上分配的内存.x的真正值是一个数据结构,它包含了一个指针,指向了堆.当我们开始执行这个函数的时候,Box::new()会被调用,这会在堆上分配一些空间,然后把5这个数放进去.内存现在看起来像这样:
地址 名字
230   5
... ... ...
1 y 42
0 x 230

Page 68

在1GB的内存中,我们假设堆的起始地址是230.因为栈地址是从0开始增加的,最简单的方法就是从另外一端开始分配.所以我们的第一个值就在内存的最高地址.另外,在x处的结构体是一个裸指针,它指向了我们分配的堆的地址,所以x的值就是230,我们分配这个地址的时候得到的值.

我们还没有真正讨论过分配和释放内存到底意味着什么.深入探讨这些内容超出了本书的范围,但是目前我们需要知道的重要的地方就是堆和栈具有相反的增长方向.本书的后面我们会有例子,因为我们可以任意的以任意的顺序分配和释放内存,这样就会在内存中形成一些"洞".这里有一个图显示出当程序运行了一段时间后的状态:
地址 名字
230   5
(230)-1    
(230)-2    
(230)-3   42
... ... ...
3 y (230)-3
2 y 42
1 y 42
0 x 230

在此例中,我们在堆上分配了4个变量,但是只释放了2个.在230和(230)-3之间有一段空隙,没有被使用.具体的细节取决于你管理内存的策略.不同的程序会使用不同的内存管理策略,通过一些库函数.Rust程序使用jemalloc来完成内存管理.

回到我们的程序来.因为这段空间分配在栈上,它可以比分配box的函数生存的更久.在此例,它并没有(生存更久).当函数结束的时候,我们会释放main()的栈帧.而Box<T>类型还有一个"小把戏":Drop.Box类型的Drop操作可以实现释放内存的功能.很好!所以当x离开作用域的时候,他释放了堆上的内存:
地址 名字
1 y 42
0 x ???

Page 69

然后栈帧也释放,内存也释放了.

4.1.4 参数和借用(borroing)
我们已经有了一些基本的关于栈和堆的例子,但是参数和借用呢?这有一个Rustxiaochengxu :
fn foo(i:&i32) {
    let z = 42;
}

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

    foo(y);
}

当我们进入main()函数是,内存是这样的:
地址 名字
1 y 0
0 x 5
x的值是基本数值5,y是x的一个引用.所以y的值就是x的内存地址,也就是0.

那么当我们调用foo()函数,并传入y参数呢?
地址 名字
3 z 42
2 i 0
1 y 0
0 x 5
栈帧并不仅仅针对局部变量,参数也是的.所以在此例中,我们同时需要参数i和z变量绑定.i就是参数y的一个拷贝.因为y的值是0,所以i也是0.

Page 70

借用并不会释放内存,原因是这样的:一个引用的值仅仅是一个指向内存地址的指针.如果我们不使用相应的内存,就无法正常工作.

4.1.5 一个复杂的例子
OK.让我们一步一的分析一个复杂的例子:
fn foo(x: &i32) {
    let y = 10;
    let z = &y;

    baz(z);
    bar(x, z);
}

fn bar(a: &i32, b: &i32) {
    let c = 5;
    let d = Box::new(5);
    let e = &d;

    baz(e);
}

fn baz(f: &i32) {
    let h = 3;
    let i = Box::new(20);
    let j = &h;

    foo(j);
}

首先,我们调用main()函数:
地址 名字
230   20
... ... ...
2 j 0
1 i 230
0 h 3

相关文章推荐

Rust中文翻译20

Page 100 并发和并行在计算机科学中是非常重要的主题.在工业领域也很火.计算机如今有越来越多的核心,然而很多程序员还没有准备好使用它们. Rust安全的内存特性同样适用于并发存储.并发的...
  • zcmit
  • zcmit
  • 2015年07月11日 15:49
  • 1176

Rust中文翻译1

用kindle看trpl有一段时间了,由于总是在地铁里看,对知识的巩固和加深理解没有好处,还是决定自己翻译一遍吧,便于自己学习,也可以给其他人以参考. 平时加班太多了,我希望能坚持做完. 闲话不说,上...
  • zcmit
  • zcmit
  • 2015年06月14日 17:16
  • 2470

Rust中文翻译12

Page 63 我们已经学习了如何写一些Rust代码了.但是能写Rust代码和能写好的Rust代码又很大区别. 这一章讲述一些相对独立的指南,告诉你如何把的Rust代码更进一步.一...
  • zcmit
  • zcmit
  • 2015年07月03日 17:11
  • 819

rust book 中文翻译

  • 2015年07月10日 12:03
  • 2.24MB
  • 下载

苹果App Store审核指南中文翻译(2014.9.1更新)

CocoaChina对《苹果应用商店审核指南》中文翻译最近一次更新时间为2014-02-27,文中红色部分是相对于2014-02-27版本的新增内容,蓝色表示苹果相关官方文档的链接。...

Gitlab部署CI并使用.gitlab-ci.yml配置您的作业(中文翻译)

本文档描述了.gitlab-ci.ymlGitLab Runner用于管理项目作业的文件的用法。 如果您想快速介绍GitLab CI,请按照我们的 快速入门指南。 .gitlab-ci.yml ...

Android Audio音频部分官网文档中文翻译

Audio 安卓音频硬件抽象层(HAL)通过 android.media 包中的音频框架 API 函数将系统上层和底层的音频驱动与硬件实体 联系起来。这一章节的内容包括实现安卓音频功能的方法说明以...

james blunt no tears 歌词的中文翻译

来自 http://zhidao.baidu.com/question/197395361.html 上面那人的歌词少了开头两句。 don't I know it, nobody has to sa...
  • huyoo
  • huyoo
  • 2011年07月26日 00:26
  • 5397

DBCP2配置详细说明(中文翻译)

common-dbcp2数据库连接池参数说明 由于commons-dbcp所用的连接池出现版本升级,因此commons-dbcp2中的数据库池连接配置也发生了变化,具体的参数配置说明如下: ...
  • kerafan
  • kerafan
  • 2015年12月22日 23:10
  • 5412

NodeMCU文档中文翻译 4 烧写固件

一、译文  Adafruit 提供了非常好的固件烧写教程 。下面你会发现两个流行的基本工具esptool和NodeMCU Flasher。 注意:记住ESP8266在烧写新固件前需要放入烧写模块。 ...
  • Leytton
  • Leytton
  • 2016年06月20日 20:04
  • 3369
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Rust中文翻译13
举报原因:
原因补充:

(最多只允许输入30个字)