Rust中指针和引用的区别是什么?

47

在Rust中,指针*和引用&具有相同的表示形式(它们都代表数据块的内存地址)。

但在编写代码时,它们之间有什么实际差异呢?

当将C++代码移植到Rust时,它们可以安全地替换吗(C++指针-> Rust指针,C++引用-> Rust引用)?


2
总的来说,在Rust中,您可以使用引用做更多的事情,而在C++中,原始指针的用途比在Rust中要多得多。如果您正在使用大多数智能指针的现代C++,那么这些指针通常可以直接转换(例如,std::unique_ptr -> Boxstd::shared_ptr -> Arc,尽管并非所有指针都是如此直截了当)。如果您的C++代码中有很多C指针,则需要评估它们的使用方式。许多C++代码不必要地使用原始指针,其中引用或智能指针会更好地工作。 - trent
6
尝试将一个C++设计直接移植到Rust可能会很困难。最好将旧设计放松心态,并使用Rust草拟一个全新的设计,而不是尝试一一转换每个函数和数据结构,并在最后将它们全部组合起来。如果旧设计包含循环数据结构或类继承,这种方法就更加适用了。 - trent
2个回答

76
当可以使用引用时,请使用引用;当必须使用指针时,请使用指针。如果您没有进行FFI或超出编译器可以验证的内存管理,那么您不需要使用指针。
引用和指针都有两种变体。有共享引用 & 和可变引用 &mut。有const指针 *const 和mut指针 *mut(在C语言中映射到const和非const指针)。然而,引用的语义与指针的语义完全不同。
引用是关于类型和生命周期的通用。共享引用的长格式为&'a T(其中'aT是参数)。在许多情况下,生命周期参数可以省略。编译器使用生命周期参数来确保引用的生命周期不会超过借用的有效期。
指针没有生命周期参数。因此,编译器无法检查特定指针是否有效。这就是为什么解引用指针被认为是unsafe的原因。
当您创建一个对象的共享引用时,该对象将被“冻结”(即在共享引用存在时,对象变为不可变),除非对象使用某种形式的内部可变性(例如使用Cell、RefCell、Mutex或RwLock)。然而,当您有一个指向对象的const指针时,该对象可能仍然在指针存在期间发生更改。
当您拥有对象的可变引用时,您保证通过此引用独占地访问该对象。任何其他访问该对象的方式要么暂时禁用,要么无法实现。例如:
let mut x = 0;
{
    let y = &mut x;
    let z = &mut x; // ERROR: x is already borrowed mutably
    *y = 1; // OK
    x = 2; // ERROR: x is borrowed
}
x = 3; // OK, y went out of scope

可变指针没有这样的保证。

引用不能为null(与C++引用类似)。指针可以为null。

指针可以包含适合于usize的任何数字值。初始化指针不是unsafe;只有对其进行解引用才是。另一方面,即使您从未对其进行解引用,产生无效引用也被认为是未定义的行为

如果您有一个*const T,则可以自由地将其转换为*const U*mut T使用as。您不能使用引用进行此操作。但是,您可以使用as将引用转换为指针,并且可以通过解引用指针(再次,这是unsafe)并使用&&mut借用该位置来“升级”指针到引用。例如:

use std::ffi::OsStr;
use std::path::Path;

pub fn os_str_to_path(s: &OsStr) -> &Path {
    unsafe { &*(s as *const OsStr as *const Path) }
}

在C++中,引用是“自动解引用指针”。而在Rust中,通常仍需要显式地解引用引用。例外情况是当您使用.运算符时:如果左侧是引用,则编译器将自动解引用它(必要时递归!)。但是,指针不会自动解引用。这意味着如果您想解引用并访问字段或方法,则需要编写(*pointer).field(*pointer).method()。在Rust中没有->运算符。

@WhyWhat,表达你对答案困惑的更好方法是有的。你到底从这里不理解什么? - E net4

3
Rust 的引用只是一个指针,但编译器赋予它们借用语义。当您获取一个不可变的对象引用时,编译器确保在派生引用消失之前,您不能修改该对象。

在Rust中,我们可以使用指针代替引用吗?也就是说,使用具有借用语义的指针? - EvanL00
3
你可以通过编写代码来做任何事情,包括那个。然而,并不是所有的想法都是好的。 - NovaDenizen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接