Rust 中指针和引用的区别

Paz*_*Paz 10 c++ porting pointers reference rust

Rust 中的指针 * 和引用 & 共享相同的表示(它们都表示一段数据的内存地址)。

编写代码时的实际区别是什么?

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

Fra*_*gné 20

尽可能使用引用,必要时使用指针。如果您不进行编译器可以验证的 FFI 或内存管理,则不需要使用指针。

引用和指针都存在于两种变体中。有共享引用&和可变引用&mut。有 const 指针*const和 mut 指针*mut(它们映射到 C 中的 const 和非常量指针)。但是,引用的语义与指针的语义完全不同。

引用在类型和生命周期内是通用的。共享引用&'a T以长格式编写(其中'aT是参数)。在许多情况下可以省略生命周期参数。编译器使用生命周期参数来确保引用的存活时间不会超过借用的有效时间。

指针没有生命周期参数。因此,编译器无法检查特定指针是否有效。这就是考虑取消引用指针的原因unsafe

当你创建一个对象的共享引用时,它会冻结对象(即当共享引用存在时对象变成不可变的),除非对象使用某种形式的内部可变性(例如使用CellRefCellMutexRwLock)。但是,当您有一个指向对象的 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
Run Code Online (Sandbox Code Playgroud)

Mut 指针没有这样的保证。

引用不能为空(很像 C++ 引用)。指针可以为空。

指针可以包含任何可以放入usize. 初始化指针不是unsafe;只是取消引用它。另一方面,产生无效引用被视为未定义行为,即使您从未取消引用它。

如果您有 a *const T,则可以自由地将其强制转换为 a*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) }
}
Run Code Online (Sandbox Code Playgroud)

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


Nov*_*zen 5

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

  • 您可以做任何您可以编写代码来做的事情,包括那件事。然而,并非一切都是好主意。 (3认同)