在 Rust 中,指针和引用有什么区别?
What are the differences between a pointer and a reference in Rust?
在Rust 中,指针*
和引用&
共享相同的表示形式(它们都表示一段数据的内存地址(。
但是,编写代码时的实际区别是什么?
将C++代码移植到 Rust 时,是否可以安全地替换它们(C++指针 --> rust 指针,C++引用 --> rust 引用(?
尽可能使用引用,必要时使用指针。如果不执行超出编译器可以验证范围的 FFI 或内存管理,则无需使用指针。
引用和指针都存在于两种变体中。&
有共享引用和可变引用&mut
。有常量指针*const
和 mut 指针*mut
(映射到 C 中的常量和非常量指针(。但是,引用的语义与指针的语义完全不同。
引用在类型和生存期内是泛型的。共享引用以长格式编写&'a T
(其中'a
和T
是参数(。在许多情况下,可以省略生存期参数。编译器使用生存期参数来确保引用的生存期不会超过借用的有效时间。
指针没有生存期参数。因此,编译器无法检查特定指针是否有效使用。这就是为什么取消引用指针被认为是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++引用非常相似(。指针可以为空。
指针可以包含任何可能适合usize
的数值。初始化指针不是unsafe
;只有取消引用它才是。另一方面,生成无效引用被视为未定义的行为,即使您从未取消引用它也是如此。
如果你有一个*const T
,你可以使用as
自由地将其投射到*const U
或*mut T
。你不能用引用来做到这一点。但是,您可以使用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 中没有->
运算符。
Rust 引用只是一个指针,但编译器赋予它们借用语义。 当您采用对对象的不可变引用时,编译器可确保在派生引用消失之前无法修改该对象。
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- Qt:remove() 和 rmdir() 有什么区别
- 这 4 个 lambda 表达式之间有什么区别?
- 将向量作为类>(值)<向量启动和向量<类>[值]有什么区别
- typedef 枚举和枚举类有什么区别?
- &C::c 和 &(C::c) 有什么区别?
- ascii 和 unicode 在处理级别有什么区别吗?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- "ABC" 和 "ABC" ) 在C++中有什么区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 两种访问I2C总线的方法有什么区别?
- 两种模板示例有什么区别?
- 这两种C++语法之间有什么区别?
- lua 5.0.2 模块和 5.3.5 有什么区别?
- C++中"typedef"、"using"、"namespace"和"using namespace"有什么区别?
- std::enable_if 和 std::enable_if_t 有什么区别?