繁体   English   中英

* const T和* mut T原始指针有什么区别?

[英]What are the differences between `*const T` and *mut T` raw pointers?

我正在编写一些不安全的Rust代码,因此我需要知道*const T*mut T的确切区别。 我认为它像&T&mut T (即你只是无法通过突变T通过&T ,周期),但是这似乎并没有这样的情况!

例如,指针包装器NonNull<T>的定义如下( source ):

pub struct NonNull<T: ?Sized> {
    pointer: *const T,
}

但是,可以通过as_ptr从此包装器获得*mut T ,其定义如下:

pub const fn as_ptr(self) -> *mut T {
    self.pointer as *mut T
}

该功能甚至没有标记为unsafe 我不允许从&T强制转换为&mut T (有充分的理由!),但是显然可以强制转换这样的指针。

Nomicon在有关方差的章节中提到*const T*mut T的方差不同:

  • *const T :协变
  • *mut T :不变

这是指针类型之间的唯一区别吗? 在我看来,这很奇怪。


指针类型之间到底有什么区别? *mut T没有*const T限制吗? 如果差异很小,那么在语言中同时包含两种指针类型的其他原因是什么?

*const T*mut T之间的区别

毫不奇怪,可变和const原始指针之间的主要区别是,取消引用它们会产生可变的还是不变的位置表达式。 取消引用const指针会产生一个不变的位置表达式 ,取消引用一个可变指针会产生一个可变的表达式 根据语言参考 ,可变性的含义是:

对于要分配,可变借用,隐式可变借用或绑定到包含ref mut mutt的模式的场所表达式,它必须是可变的。

正如您已经指出的,const和可变指针之间的另一个区别是类型的差异,我认为这就是全部。

在可变和const指针之间进行转换

您可以在安全代码中将*const T转换为*mut T ,因为一旦取消引用指针,可变性的差异就变得很重要,并且反引用原始指针无论如何都是不安全的操作。 如果不强制转换为可变指针,则无法获得const指针指向的内存的可变位置表达式。

Rust可以对原始指针的可变性更加放松的原因之一是,与引用相比,它没有对原始指针的别名进行任何假设。 请参阅取消原始指针的语义是什么? 有关更多详细信息。

为什么NonNull使用*const T

NonNull指针类型用作BoxRc等智能指针的构造块。 这些类型公开了遵循常规Rust引用规则的接口-只有通过拥有或可变引用智能指针本身,才可以更改指针,并且只能通过借用智能指针本身来获得对指针的共享引用。 。 这意味着这些类型是协变的是安全的,只有在NonNull是协变的情况下才有可能,这又意味着我们需要使用*const T而不是*mut T

如果语言如此相似,为什么它们包含两种不同的指针?

让我们考虑一下替代方案。 如果只有一个指针类型,则必须是可变指针–否则我们将无法通过原始指针进行任何修改。 但是该指针类型也需要是协变的,因为否则我们将无法构建协变智能指针类型。 (始终可以通过在结构中包含PhantomData<some invariant type>来放弃协方差,但是一旦您的结构之一被其成员变为不变,就无法再次使其协变。)由于可变引用是不变的,此虚构指针类型的行为将有些令人惊讶。

另一方面,具有两种不同的指针类型可以很好地类似于引用:const指针是协变的,并且对不可变的位置表达式的引用,就像共享引用一样;可变指针是不变的,并且对可变的位置表达式的引用,就像可变的一样参考。

我只能推测这是否是设计该语言的真正原因,因为我找不到有关该主题的任何讨论,但是这个决定对我来说似乎并不合理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM