Movatterモバイル変換


[0]ホーム

URL:


codecamp

'Deref'强制转换

'Deref'强制转换

标准库提供了一个特殊的特征,Deref。它通常用于重载 * ,取消引用运算符:

use std::ops::Deref;struct DerefExample<T> {value: T,}impl<T> Deref for DerefExample<T> {type Target = T;fn deref(&self) -> &T {&self.value}}fn main() {let x = DerefExample { value: 'a' };assert_eq!('a', *x);}

这用于编写自定义指针类型。然而,有一个与 Deref 相关的语言特征:‘deref 强制转换’。规则是这样的:如果你有一个类型 U,它实现Deref<Target=T>,&U 的值自动强制转换为 &T。这里有一个例子:

fn foo(s: &str) {// borrow a string for a second}// String implements Deref<Target=str>let owned = "Hello".to_string();// therefore, this works:foo(&owned);

在一个值前使用 & 需要一个引用。所以 owned 是一个 String,&owned 是一个 &String,并且由于impl Deref<Target=str> for String,&String 参考传入函数 foo() 的 &str。

就这样。这条规则是 Rust 为你自动转换的少有的几处之一,但它增加了很大的灵活性。例如,类型Rc<T> 实现Deref<Target=T>,所以它的工作原理如下:

use std::rc::Rc;fn foo(s: &str) {// borrow a string for a second}// String implements Deref<Target=str>let owned = "Hello".to_string();let counted = Rc::new(owned);// therefore, this works:foo(&counted);

所有我们所做的就是把我们的 String 封装到Rc<T>。但是我们现在可以把Rc<String> 传到任何有 String 的地方。foo 的声明并没有改变,但能实现与其它类型一样的功能。这个例子有两个转换:Rc<String> 转换为 String,然后 String 转换为 &str。Rust 会这样做尽可能多的次数直到类型匹配。    

标准库提供的另一个很常见的实现是:

fn foo(s: &[i32]) {// borrow a slice for a second}// Vec<T> implements Deref<Target=[T]>let owned = vec![1, 2, 3];foo(&owned);

向量可以取消对程序片的引用。

Deref 和方法调用

Deref 调用方法时也起作用。换句话说,Rust 有相同的两件事:

struct Foo;impl Foo {fn foo(&self) { println!("Foo"); }}let f = Foo;f.foo();

尽管 f 不是引用,但是函数 foo 中传入 &self 就会起作用。这是因为这些东西是相同的:

f.foo();(&f).foo();(&&f).foo();(&&&&&&&&f).foo();

&&&&&&&&&&&&&&&&Foo 类型的值仍然可以有定义在 Foo 上的方法,因为编译器会插入许多 操作只要程序正确运行。因为它的插入 s,就要使用 Deref。

操作符和重载
宏命令
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录
关于
介绍

新手入门

学习 Rust

高效 Rust

语法和语义

Nightly Rust

词汇表
相关学术研究

关闭

MIP.setData({'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false},'pageFontSize' : getCookie('pageFontSize') || 20});MIP.watch('pageTheme', function(newValue){setCookie('pageTheme', JSON.stringify(newValue))});MIP.watch('pageFontSize', function(newValue){setCookie('pageFontSize', newValue)});function setCookie(name, value){var days = 1;var exp = new Date();exp.setTime(exp.getTime() + days*24*60*60*1000);document.cookie = name + '=' + value + ';expires=' + exp.toUTCString();}function getCookie(name){var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null;}
[8]ページ先頭

©2009-2025 Movatter.jp