Rust之介绍

声明:本系列博客是从Rust官网的教程中翻译过来。官网教程地址

欢迎!这本书将会教你有关于Rust这门编程语言。Rust是系统编程语言,它专注于三个目标:安全、效率和并发。这本书被分为八个部分:

  • 开始入门:搭建环境来开发Rust
  • 学习Rust: 通过小的项目来学习Rust
  • 高效的Rust:使用高级的概念来书写完美的Rust代码
  • 语法知识: 将零碎的代码集成代码块
  • 不稳定的Rust: 还没有实现的前沿技术
  • 词汇表: 书中术语的参考
  • 学术研究: 影响Rust的文学

下面我将会给出一些代码例子来展示一个Rust的特点

1.让Rust独特的主要方面是’ownership’。看一下代码:

fn main(){
    let mut x=vec!["Hello","World"];
}

讲解:
上面这段程序对x进行了变量绑定。绑定的值是Vec,它是一个’vector’(可以理解为容器),我们可以通过定义在标准库中的宏指令来创建。这个宏指令叫做Vec,我们使用一个感叹号’!’来调用它。这遵循了Rust的一项基本原则:简单清晰。宏可以比函数调用做更复杂的事情。感叹号!也有助于解析,让工具更容易去,当然,这也是很重要的。

我们使用mut使x可变的:在Rust中,绑定是不可变的。稍后在例子中,我们会改变这个’vector’(即容器)。

我们是不需要进行类型声明的:尽管Rust是静态类型的,我们也不需要明确地进行类型声明。Rust有类型推测功能来减少类型声明的冗余。

Rust使用栈(stack)来进行内存分配,丢弃了堆。x被直接放在了栈中,但是Vec是在队(heap)中为容器中的元素进行内存分配的。作为系统编程语言,Rust赋予你能力来控制你的内存是如何分配的。

先前,我们提到’ownership’是Rust中关键的概念。用Rust的说法讲可,”x ‘own’ the vector(x 拥有容器)”,意味着一旦x销毁的时候,容器的内存会自动销毁。这并不是垃圾回收器完成的,而是由Rust来完成的。换句话说,在Rust中,你不必亲自调用像malloc或free这样的函数因为编译器会自动地帮你决定什么时候需要分配或者是销毁内存并且在适当的时候来调用这些函数。

2.在上面的代码例子中,我们添加另一行:

fn main(){
    let mut x=vec!["Hello","World"];
    let y=&x[0];

讲解:
我们来介绍另一种对y绑定,在上面的例子中,y是对容器第一个元素的引用。Rust的引用类似于其他语言的指针,但会增加编译时的安全检查。引用是通过向它们所指向的内容所属的所有权系统“借,而不是拥有所指向的内容(borrow)”来与所有权系统进行交互。区别是,当引用销毁的时候,不会销毁内存。

我们来添加第三段代码。看起来好像没有一点问题,但是会引起编译器问题。

fn main(){
    let mut x=vec!["Hello","World"];
    let y=&x[0];
    x.push("foo");
}

push是容器中的方法,作用是在容器的尾端添加另一个元素。我们尝试来编译这个程序,会发生一个错误。

error.rs:4:2: 4:3 error: cannot borrow `x` as mutable because it is also borrowed as immutable
error.rs:4  x.push("foo");
            ^
error.rs:3:9: 3:10 note: previous borrow of `x` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `x` until the borrow ends
error.rs:3  let y=&x[0];
                   ^
error.rs:5:2: 5:2 note: previous borrow ends here
error.rs:1 fn main(){
error.rs:2  let mut x=vec!["Hello","World"];
error.rs:3  let y=&x[0];
error.rs:4  x.push("foo");
error.rs:5 }
           ^
error: aborting due to previous error

Rust编译器有时会给出非常详细的错误。就像错误所解释的那样,当我们让绑定可变的时候,我们仍然不可以调用push这个方法,这是因为我们已经有一个指向容器元素的引用,y。当一个东西有引用指向它却仍要改变它的时候是非常危险的,因为我们可能会使引用无效。在这个具体的例子中,当我们创建了一个容器,只会为两个元素分配内存空间。在容器中添加第三个元素意味着会为容器总的所有元素分配新的内存空间,将原来元素的值拷贝,并且更新内部指向内存的指针。问题是y不会更新,所以,我们有一个危险的指针。只要使用y的会就会发生错误,所以编译器会提示这个错误。

3.那么如何解决这个问题呢?我们可以采取两种解决方案。

<1>进行拷贝,而不是使用引用

fn main(){
    let mut x=vec!["Hello","World"];
    let y=x[0].clone();
    x.push("foo");

讲解:
Rust默认拥有move语法,所以如果我们想拷贝一些数据时,可以调用clone()方法。在这个例子中,y不再是存储在x中的容器的引用,而是容器中第一个元素”Hello”的拷贝。现在就可以调用push()这个方法了。

<2>如果我们实在想要一个引用,我们需要另外一个选择:确保我们改变的时候让引用离开作用域。

fn main(){
    let must x=vec!["Hello","World"];
    {
        let y=&x[0];
    }
    x.push("foo");
}

我们需要用”{ }”来创建一个内部的作用域,在我们调用push()方法前,y会离开作用域。

ownership所有权的概念不仅仅对预防危险指针有好处,对整个系列相关问题,像遍历无效、并发等问题也有好处。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值