Rust 中指针和引用的区别 [英] Differences between a pointer and a reference in Rust

查看:259
本文介绍了Rust 中指针和引用的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

A pointer * and a reference & in Rust share the same representation (they both represent the memory address of a piece of data).

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

What's the practical differences when writing code though?

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

When porting C++ code to Rust can they be replaced safely (c++ pointer --> rust pointer, c++ reference --> rust reference ) ?

推荐答案

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

Use references when you can, use pointers when you must. If you're not doing FFI or memory management beyond what the compiler can validate, you don't need to use pointers.

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

Both references and pointers exist in two variants. There are shared references & and mutable references &mut. There are const pointers *const and mut pointers *mut (which map to const and non-const pointers in C). However, the semantics of references is completely different from the semantics of pointers.

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

References are generic over a type and over a lifetime. Shared references are written &'a T in long form (where 'a and T are parameters). The lifetime parameter can be omitted in many situations. The lifetime parameter is used by the compiler to ensure that a reference doesn't live longer than the borrow is valid for.

指针没有生命周期参数.因此,编译器无法检查特定指针是否有效.这就是为什么取消引用指针被认为是unsafe.

Pointers have no lifetime parameter. Therefore, the compiler cannot check that a particular pointer is valid to use. That's why dereferencing a pointer is considered unsafe.

当你创建一个对象的共享引用时,它会冻结对象(即当共享引用存在时对象变得不可变),除非对象使用某种形式的内部可变性(例如使用 CellRefCellMutexRwLock).但是,当您有一个指向对象的 const 指针时,该对象可能在指针处于活动状态时仍会发生变化.

When you create a shared reference to an object, that freezes the object (i.e. the object becomes immutable while the shared reference exists), unless the object uses some form of interior mutability (e.g. using Cell, RefCell, Mutex or RwLock). However, when you have a const pointer to an object, that object may still change while the pointer is alive.

当您拥有一个对象的可变引用时,保证可以通过此引用独占访问该对象.任何其他访问对象的方式要么被暂时禁用,要么无法实现.例如:

When you have a mutable reference to an object, you are guaranteed to have exclusive access to that object through this reference. Any other way to access the object is either disabled temporarily or impossible to achieve. For example:

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 指针没有这样的保证.

Mut pointers have no such guarantee.

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

A reference cannot be null (much like C++ references). A pointer can be null.

指针可以包含任何适合usize 的数值.初始化指针不是不安全;只是取消引用它.另一方面,产生无效引用被认为是未定义行为,即使您从未取消引用它.

Pointers may contain any numerical value that could fit in a usize. Initializing a pointer is not unsafe; only dereferencing it is. On the other hand, producing an invalid reference is considered undefined behavior, even if you never dereference it.

如果你有一个 *const T,你可以使用 *const U*mut T 自由地将它强制转换为 *const U*mut T代码>作为.你不能用引用来做到这一点.但是,您可以使用 as 转换对指针的引用,并且可以升级"指针.通过取消引用指针(同样是 unsafe)然后使用 &&mut 借用该位置来指向引用的指针.例如:

If you have a *const T, you can freely cast it to a *const U or to a *mut T using as. You can't do that with references. However, you can cast a reference to a pointer using as, and you can "upgrade" a pointer to a reference by dereferencing the pointer (which, again, is unsafe) and then borrowing the place using & or &mut. For example:

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 中没有 -> 操作符.

In C++, references are "automatically dereferenced pointers". In Rust, you often still need to dereference references explicitly. The exception is when you use the . operator: if the left side is a reference, the compiler will automatically dereference it (recursively if necessary!). Pointers, however, are not automatically dereferenced. This means that if you want to dereference and access a field or a method, you need to write (*pointer).field or (*pointer).method(). There is no -> operator in Rust.

这篇关于Rust 中指针和引用的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆