Rust中文翻译1

时间:2021-05-01 14:51:52

用kindle看trpl有一段时间了,由于总是在地铁里看,对知识的巩固和加深理解没有好处,还是决定自己翻译一遍吧,便于自己学习,也可以给其他人以参考.

平时加班太多了,我希望能坚持做完.

闲话不说,上第一章:


Page 11                                                                  1 导读
欢迎!本书将会教您Rust编程语言(the Rust Programming Language).Rust是一种系统 编程语言,主要关注于3个目标:安全、速度、并发。Rust语言实现这3个目标并非通过垃圾回收器 (garbage collector),作为一个非常有用的编程语言,它具有其他编程语言的并不擅长的优 点:可嵌入其他语言、实现一个有明确的时间和空间资源占用的程序、编写底层(low-level)代码.Rust在现代编程语言的基础上,通过一个改进来达到上述目标:在编译时进行一系列安全检查从而降低运 行时负担,同时可以消除资源竞争.Rust同时致力于实现一个"零成本抽象"(zero-cost abstractions),即便某些抽象看起来像是在其他高级语言中的抽象一样.即使如此,Rust仍然可以允许像一个底层语言一样进行一些底层控制.
本书分为7个部分.这篇导论是第一部分,随后是: 开始(第2章),为你的电脑设置Rust开发环境 学习Rust(第3章),通过一些小程序学习Rust 高效Rust(第4章),编写出色Rust代码的一些高层指导 语法和语义(第5章),Rust代码的每个字节在这里介绍,通过分析很小的代码片段 每日更新的Rust(第6章),Rust语言还不稳定的一些最前沿的特性 术语表(第7章),本书术语的一份索引 学术研究(第8章),涉及到Rust的一些学术著作

读完本导论后,你可以选择是进行"学习Rust"的部分还是"语法和语义"的部分,取决于你是想先看看Rust的实际的程序,还是先从小的代码片段开始学习.在这两个部分之间同时会有很多交叉引用.

Page 12 1.1 贡献 本书的所有源代码可以在Github找到: github.com/rust-lang/rust/tree/master/src/doc/trpl
1.2 Rust简介 您对Rust语言感兴趣么?让我们来写一片小代码像你展示它的强大. Rust语言最重要的概念就是"所有权"(ownership).看看下面的小例子: Rust中文翻译1
这个程序使用了一个"可变绑定"(variable binding)(5.1节)x.这个绑定的值是一个vector Vec<T>,通过一个在标准库中定义的一个宏(5.35节)来实现.这个宏就叫做vec,我们调用宏的时候使用一个!标点.这里体现出了一个Rust语言的通用指导原则:让所有事情都显式调用.宏是比函数更复杂的概念,他们看起来也是不一样的.这个!标点可以帮助编译器解析代码,让工具更容易编写,这是很重要的.
我们使用"mut"关键字,因为绑定默认是不可变的.我们会在后面的示例中改变这个vector的值.
这里我们需要注意的是,我们不需要声明一个变量的类型:虽然Rust语言是静态类型语言,但是我们不需要显式声明一个变量的类型.Rust拥有类型推导能力来平衡静态类型的高效率和书写繁冗类型声明低效率之间的关系.
Rust语言倾向于在栈上分配空间而不是堆:x是一个直接存在于栈上的变量.然而,Vec<T>类型为它的每个元素在堆上分配空间.如果你还不清楚二者的区别,你现在可以暂时忽略这一点,或者去看看"栈和堆"这一章(4.1节).作为一个系统级别的编程语言,Rust语言允许你自己控制内存分配,当我们开始学习这一点,一切都会很容易.
较早前,我提到了"所有权"(ownership)的概念是Rust语言的核心新概念.在Rust的说法中,我们会读作:"x'拥有'这个vector".这意味着,当x离开它的作用域的时候,这个vector的内存空间也会被释放(de-allocated).这是由Rust编译器决定的,而不是由类似垃圾回收器的机制完成的.换句话说,在Rust语言中,你不需要亲自调用类似malloc和free这样的函数,Rust编译器会在编译期静态的决定什么时候需要分配和释放内存,并且会自动插入这些调用.认识会犯错的,编译器永不会犯错(To err is to be human, but compilers never forget).
让我们在示例中再加一行代码:
Page 13
Rust中文翻译1
我们引入了另一个绑定,y.在这个例子中,y是一个对vector中第一个元素的"引用"(reference).Rust语言中的references类似于其他语言中的指针,但是具有编译期安全检查.References使用"借用"(borrowing)的概念和ownership一起工作,references"借用"(borrowing)他们指向的对象,而不是"拥有"(owning)他们.两者的差别是,当reference离开作用域,它不会释放所指向对象的内存空间.如果它释放了,那就会存在两次释放同一内存,这里就出问题了!
让我们再加第三行代码.它看起来正常,但是会有编译错误: Rust中文翻译1
push是一个vector类型的方法,用来在vector末尾增加一个元素.当我们试图编译这段代码的时候,我们得到了如下错误: Rust中文翻译1
哇哦!Rust编译器给出了如此详细的错误信息.正如这个错误信息所示,当我们使用了一个可变绑定时,我们仍然无法调用push.这是因为我们已经使用了一个reference y指向了vector中的一个元素.当其他reference存在的时候改变这个变量的值是很危险的行为,因为我们可能会使这个reference无效.在这个例子中,当我们创建这个vector的时候,我们只分配了3个元素的空间.增加第4个元素意味着我们需要重新分配一块更大的内存来容纳所有元素,同时还要将旧的元素拷贝到新分配的空间中去,并且更新内部的指针到新的内存地址.这些都没有问题.问题在于y不会得到更新,所以我们就会有一个野指针(dangling pointer).这就糟糕了.任何对于y的使用都会发生错误,而编译器为我们捕捉到这一点了.
Page 14 那么我们怎么解决这个问题呢?有2个方法.第1就是我们拷贝一下这个元素的值而不是仅仅使用一个引用: Rust中文翻译1
Rust语言默认是有"移动"(move)语义的,所以我们想拷贝数据的话就是用clone()方法.这里,y不在是一个指向x中元素的reference,而是这个元素的拷贝:"Hello".这里我们没有reference,我们的pus()函数可以正常工作了.
如果我们确实想使用reference,我们需要另想办法:确保我们的引用在变量改变以前离开自己的作用域就可以了.看起来像这样的: Rust中文翻译1

我们通过一对大括号创建了一个内部作用域.在push()以前y就会离开自己的作用域,所以我们可以正确执行了.
所有权的概念不仅仅可以防止野指针,同时可以解决一系列相关的问题,例如迭代器失效(iterator invalidation),并发(concurrency)等等.