- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一些不安全的 Rust 代码,所以我需要知道 *const T
之间的确切区别和 *mut T
.我认为它就像 &T
和 &mut T
(即你不能通过 T
改变 &T
,句号),但事实并非如此!
例如指针包装NonNull<T>
定义如下 ( source ):
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
但是,有可能获得 *mut T
从这个包装器通过 as_ptr
,其定义为:
pub const fn as_ptr(self) -> *mut T {
self.pointer as *mut T
}
函数甚至没有标记为 unsafe
!我不允许从 &T
转换至 &mut T
(有充分的理由!),但显然这样的指针是可以的。
Nomicon 在 the chapter about variance 中提到那*const T
和 *mut T
方差不同:
*const T
: covariant*mut T
: invariant
这是指针类型之间的唯一区别吗?这对我来说似乎很奇怪......
指针类型之间到底有什么区别?*const T
有限制吗?那*mut T
没有?如果差异很小:在语言中包含这两种指针类型的其他原因是什么?
最佳答案
*const T
之间的区别和 *mut T
毫不奇怪,可变和常量原始指针之间的主要区别在于,取消引用它们会产生可变还是不可变的位置表达式。取消引用 const 指针会产生不可变的 place expression , 取消引用一个可变指针会产生一个可变指针。可变性的含义 according to the language reference这是:
For a place expression to be assigned to, mutably borrowed, implicitly mutably borrowed, or bound to a pattern containing
ref mut
it must be mutable.
const 和可变指针之间的另一个区别是类型的差异,正如您已经指出的,我认为仅此而已。
你可以投一个*const T
到 *mut T
在安全代码中,因为可变性的差异只有在您取消引用指针后才变得相关,并且取消引用原始指针无论如何都是不安全的操作。如果不强制转换为可变指针,则无法为 const 指针指向的内存获取可变位置表达式。
Rust 可以对原始指针的可变性放宽一点的一个原因是,与引用相比,它不对原始指针的别名做出任何假设。参见 What are the semantics for dereferencing raw pointers?了解更多详情。
NonNull
使用 *const T
?NonNull
指针类型用作智能指针的构建 block ,如 Box
和 Rc
.这些类型公开了遵循通常的 Rust 引用规则的接口(interface)——指针对象的变异只能通过智能指针本身的所有权或可变引用来实现,并且指针对象的共享引用只能通过借用智能指针本身来获得.这意味着这些类型协变是安全的,只有在 NonNull
时才有可能。是协变的,这反过来意味着我们需要使用 *const T
而不是 *mut T
.
让我们考虑替代方案。如果只有一个指针类型,它必然需要是可变指针——否则我们将无法通过原始指针修改任何内容。但是该指针类型也需要是协变的,否则我们将无法构建协变智能指针类型。 (总是可以通过在结构中包含 PhantomData<some invariant type>
来放弃协变性,但是一旦您的结构被其成员之一呈现为不变性,就无法使其再次协变。)由于可变引用是不变的,因此行为这种虚构的指针类型会有些令人惊讶。
另一方面,拥有两种不同的指针类型可以很好地类比引用:const 指针是协变的并且对不可变位置表达式解引用,就像共享引用一样,而可变指针是不变的并且对可变位置表达式解引用,就像可变引用一样。
我只能推测这些是否是语言设计的真正原因,因为我找不到关于该主题的任何讨论,但这个决定对我来说似乎并非不合理。
关于pointers - `*const T` 和 *mut T` 原始指针有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55664870/
Rust 中 *、&、mut、&mut、ref、ref mut 的用法和区别 在 Rust 中,*、ref、mut、& 和 ref mut 是用于处理引用、解引用和可变性的关
这个问题在这里已经有了答案: How to avoid writing duplicate accessor functions for mutable and immutable referenc
我正在尝试使用指向我的结构的指针调用 pthread_join,以便 C 线程可以将结构填充到我指向它的内存中。 (是的,我知道这是非常不安全的..) pthread_join的函数签名: pub u
这个问题在这里已经有了答案: is it possible to filter on a vector in-place? (4 个答案) Is there a way to drain parts
这个问题在这里已经有了答案: is it possible to filter on a vector in-place? (4 个答案) Is there a way to drain parts
以下代码编译失败,因为 MutRef 不是Copy。无法复制,因为&'a mut i32 不是Copy。有什么方法可以让 MutRef 具有与 &'a mut i32 相似的语义吗? 这样做的动机是能
我想转换数组。 例子: func()-> *mut *mut f32; ... let buffer = func(); for n in 0..48000 { buffer[0][n] =
我想对 &mut [u8] 进行一些操作。 在我的测试代码中我有: #[test] fn test_swap_bytes() { let input: &[u8] = b"abcdef";
首先,我不是在问 &mut 之间有什么区别?和 ref mut本身。 我问是因为我想: let ref mut a = MyStruct 与相同 let a = &mut MyStruct 考虑从函数
这个问题在这里已经有了答案: What's the difference between placing "mut" before a variable name and after the ":"
我正在从书中学习 Rust,并且我正在处理第 8 章末尾的练习,但是关于将单词转换为 Pig Latin 的练习我遇到了困难。我想具体看看我是否可以将 &mut String 传递给一个接受 &mut
这段代码: let mut a2 = 99; let b: *mut i32 = &mut a2; *b = 11; // does not compile , even after unsafe {
我正在尝试了解借用检查器。我有一个带有签名的函数 fn SerializeChar(&mut self, value: &mut u8) 我想从 u8 和 i8 获取数据,因为我不关心符号: let
在下面的示例中,t1 编译但 t2 不编译。 &mut &stream有什么特别之处吗?我认为 Deref 不会起作用。 use std::net::TcpStream; fn t1() {
我正在围绕 C 库编写一个 Rust 包装器,同时我正在尝试利用 The Book 中提到的“可空指针优化” , 但我找不到转换 Option 的好方法至 *const T和 Option至 *mut
我试图在 Rust 中实现一个链表,但我在理解这两个函数之间的区别时遇到了一些困难: enum List { Nil, Cons(T, Box>) } fn foo(list: &mu
根据文档,ManuallyDrop是一个零成本包装器。这是否意味着我可以取消引用指向 ManuallyDrop 的原始指针从原始指针转换为 T ? 最佳答案 ManuallyDrop 是 declar
我一直在尝试用 Rust 编写 Redis 模块。这是我第一次尝试使用 Rust FFI 和绑定(bind)。如何在不破坏 Redis 指针的情况下调用此方法并在 Rust 中得到一个数据值? ext
我很难理解以下代码为何具有2种不同的行为: pub fn get(&self, idx: usize) -> &T { let arr = unsafe { core::slice::from
在 documentation为 Unwindsafe我们有: Types such as &mut T and &RefCell are examples which are not unwind
我是一名优秀的程序员,十分优秀!