给定以下代码:
fn main() {
let a: i32 = 1;
let b: &i32 = &a;
let c: String = "hello world".to_string();
let d: &str = &c[..];
}
我知道了
a
是一个正常的变量,b
是保存指针的引用c
是一个引用,尽管它是一个智能引用,因为除了保存指针之外,它还包含其他数据,如长度、容量等。d
是一个引用,不是一个聪明的引用,但我看到的通常被称为胖指针。它包含指针和简单的额外信息,如指向的数据的长度。
好了,现在我的问题是,有没有一种方法可以在编译时检查这些变量或类型,以知道它们是哪种类型的引用?
我知道有几个函数可以用来内省类型。比如std::mem::size_of
和std::mem::align_of
。我想知道有没有可以用来推断某个东西是什么类型的引用的函数?
2条答案
按热度按时间chhkpiq41#
看起来,你并不完全理解rust-land中的引用是什么,你的描述表明你对C++中的引用有着非常相似的理解,但是在rust-land中,它是完全不同的。
在rust中,引用是类型。
T
、&T
和&mut T
是三种不同的类型。它们类似于指针,但有额外的保证,其中最重要的是:你也可以有对其他引用的引用(就像在C中你可以有一个指针对一个指针),所以
T
,&T
,&&T
,&&&T
等是不同的类型。现在当我们说某个东西是一个引用时,它意味着它的类型是某种类型的引用。
a
具有类型i32
(带符号的整数)b
的类型为&i32
,因此它是对数字的引用c
有一个String
类型,它不是一个引用。当然,它内部包含一个指向堆分配缓冲区的指针,但是String
类型只是String
,而不是对任何其他类型的引用d
的类型是&str
,它是一个引用。更具体地说,它是一个字符串slice的引用。正如您所指出的,它是一个“胖”指针,因为它不仅包含了切片开始的地址,而且还包含了切片的长度。所以最后解决你的问题。在rust中只有两种引用,共享的
&T
和独占的由于所有类型必须在编译时知道,所以没有任何运行时内省或反射函数来告诉你什么类型的引用是某个类型。rust中没有“智能引用”这样的东西,但是有一种叫做smart pointers的东西,尽管它是非常不同的东西。kmbjn2e32#
如果您只想知道引用指向什么,那么您可以使用
ToOwned
特征(例如:<str as ToOwned>::Owned
的计算结果为String
)。但是,在我看来,您可能需要的是Cow<'a, T>
。它们的名称代表Clone On Write。在它们的核心,它们只是引用或拥有值的枚举。它们对于字符串和切片的操作非常有用,您可能需要修改输入,但如果输入已经有效,则不希望复制所有数据。主要优点是它们可以被视为拥有值,但给予您根据性能灵活地在两者之间切换。
作为一个有趣的附带点,如果我们只理解问题的标题,那么编写一个在编译时解析为一个值的简单
is_ref<T>()
函数并不太难。它使用了类似于impls
crate的特征。这可能很有趣,但可能并不是那么有帮助。