在Rust中,指针*
和引用&
具有相同的表示形式(它们都代表数据块的内存地址)。
但在编写代码时,它们之间有什么实际差异呢?
当将C++代码移植到Rust时,它们可以安全地替换吗(C++指针-> Rust指针,C++引用-> Rust引用)?
&
和可变引用 &mut
。有const指针 *const
和mut指针 *mut
(在C语言中映射到const和非const指针)。然而,引用的语义与指针的语义完全不同。&'a T
(其中'a
和T
是参数)。在许多情况下,生命周期参数可以省略。编译器使用生命周期参数来确保引用的生命周期不会超过借用的有效期。unsafe
的原因。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) }
}
.
运算符时:如果左侧是引用,则编译器将自动解引用它(必要时递归!)。但是,指针不会自动解引用。这意味着如果您想解引用并访问字段或方法,则需要编写(*pointer).field
或(*pointer).method()
。在Rust中没有->
运算符。
std::unique_ptr
->Box
,std::shared_ptr
->Arc
,尽管并非所有指针都是如此直截了当)。如果您的C++代码中有很多C指针,则需要评估它们的使用方式。许多C++代码不必要地使用原始指针,其中引用或智能指针会更好地工作。 - trent