Skip to the content.

从C++的RAII到Rust的所有权(二)

Contact me


上次我们说到两种对象传递方法:复制和移动[引用],默认变量是不变的,对象只有一个引用,听起来是个非常纯粹的做法,但是相比我们一般的做法有些束手束脚,这样有什么好处呢?

数据竞争(data race)是一种特定类型的竞争状态,它可由这三个行为造成:

来自《Rust程序设计语言》

Rust天生的不存在这个问题,这些问题在编译时就会被发现。

但是故事还没有结束,我们要获取对象的一部分怎么办?

// 获取第一个单词
fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);
    s.clear(); // Error!
}

所有者清空了,我们获得的对象部分也无效了,所以这个是不能编译的,所以一个规则是一个时间内不能可变和不可变引用同时存在。

来自《Rust程序设计语言》

这样我们保证了在需要变的时候,只有一个变化者,不变的时候,多少不可变都是无害的。

回想一下C++,我们默认是可变的,所以很容易出现数据竞争,多线程下需要小心。

似乎已经说完了,但是引用有个麻烦的特性,不知道你注意到没有那就是我们眼皮子底下的:引用必须总是有效的。有时候我们不能这样保证,比如我们要实现链表,我们不能第一步就确定好节点的下一个节点是啥,所以类似一系列原因,Rust还是引入了指针,指针又回来了!!

哈哈,并没有变得简单,只不过这些语言特性在内存管理,垃圾回收等方面提供了很大便利,Rust的指针是个什么鬼,和C++的指针一样吗,我们后续再聊。