c++ - Rust 中指针和引用的区别

标签 c++ pointers rust reference porting

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

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

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

最佳答案

尽可能使用引用,必要时使用指针。如果您不进行编译器可以验证的 FFI 或内存管理,则不需要使用指针。
引用和指针都存在于两种变体中。有共享引用&和可变引用 &mut .有常量指针 *const和 mut 指针 *mut (映射到 C 中的常量和非常量指针)。但是,引用的语义与指针的语义完全不同。
引用在类型和生命周期内是通用的。共享引用写成&'a T长格式(其中 'aT 是参数)。生命周期参数可以是 omitted在许多情况下。编译器使用生命周期参数来确保引用的存活时间不会超过借用的有效时间。
指针没有生命周期参数。因此,编译器无法检查特定指针是否有效。这就是为什么取消引用指针被认为是 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
Mut 指针没有这样的保证。
引用不能为空(很像 C++ 引用)。指针可以为空。
指针可以包含任何可以放入 usize 的数值。 .初始化指针不是unsafe ;只是取消引用它。另一方面,产生无效引用被认为是 undefined behavior ,即使您从未取消引用它。
如果您有 *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 中,您通常仍然需要显式地取消引用引用。异常(exception)情况是当您使用 . 时运算符:如果左侧是引用,编译器将自动取消引用它(如有必要,递归!)。然而,指针不会自动解除引用。这意味着如果要取消引用和访问字段或方法,则需要编写 (*pointer).field(*pointer).method() .没有-> Rust 中的运算符。

关于c++ - Rust 中指针和引用的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62232753/

相关文章:

c - 需要澄清指针在给定代码段中如何工作

rust - 为什么我需要导入特征才能使用它为类型定义的方法?

c++ - 包装类 C++

c++ - 标志如何在 C 中工作?

c++ - C++中的空引用检查

rust - 从语义的角度来看,Rust 中发生 `&mut` noalias 的未定义行为是什么时候?

string - 返回结果,带无引号的字符串

c++ - 为什么 MSVC++11 拒绝函数的 constexpr 限定?

c++ - 如何使用 C++ 将时区化的 XML 类型 dateTime 转换为 time_t

c - 使用 malloc 初始化指向结构体的指针