鍍金池/ 教程/ Java/ Deref
標準輸入與輸出
消息傳遞
循環(huán)
注釋
Rust for Mac OS
幾種智能指針
Cell, RefCell
trait對象 (trait object)
rust web 開發(fā)
Unsafe、原始指針
Macro
迭代器
函數(shù)
Borrow, BorrowMut, ToOwned
快速上手
二叉樹
編輯器
測試與評測
Deref
安裝Rust
哈希表 HashMap
原生類型
17.錯誤處理
VS Code 安裝配置
動態(tài)數(shù)組Vec
模式匹配
操作符和格式化字符串
Rust for Linux
函數(shù)參數(shù)
Visual Studio
vim/GVim安裝配置
閉包作為參數(shù)和返回值
安全(Safety)
Cow
生命周期( Lifetime )
閉包的實現(xiàn)
所有權(quán)(Ownership)
Atom
將Rust編譯成庫
類型、運算符和字符串
類型系統(tǒng)中的幾個常見 trait
特性
屬性和編譯器參數(shù)
Spacemacs
集合類型
Rust json處理
Heap & Stack
并行
標準庫示例
基本程序結(jié)構(gòu)
鏈表
trait 和 trait對象
前期準備
代碼風格
編譯器參數(shù)
基于語義化版本的項目版本聲明與管理
Rust 版本管理工具: rustup
引用&借用(References&Borrowing)
注釋與文檔
10.1 trait關(guān)鍵字
模式
調(diào)用ffi函數(shù)
unsafe
并發(fā),并行,多線程編程
AsRef 和 AsMut
Rust旅程
Rust for Windows
結(jié)構(gòu)體與枚舉
條件分支
附錄I-術(shù)語表
變量綁定與原生類型
Mutex 與 RwLock
泛型
裸指針
常用數(shù)據(jù)結(jié)構(gòu)實現(xiàn)
系統(tǒng)命令:調(diào)用grep
Into/From 及其在 String 和 &str 互轉(zhuǎn)上的應用
共享內(nèi)存
Sublime
網(wǎng)絡模塊:W貓的回音
函數(shù)返回值
包和模塊
高階函數(shù)
函數(shù)與方法
match關(guān)鍵字
隊列
目錄操作:簡單grep
語句和表達式
并發(fā)編程
閉包
測試
閉包的語法
同步
迭代器
String
Send 和 Sync
Rc 和 Arc
屬性
Emacs
優(yōu)先隊列
Prelude
cargo簡介
控制流(control flow)
數(shù)組、動態(tài)數(shù)組和字符串
FFI
模塊和包系統(tǒng)、Prelude
實戰(zhàn)篇
Rust 是一門系統(tǒng)級編程語言,被設計為保證內(nèi)存和線程安全,并防止段錯誤。作為系統(tǒng)級編程語言,它的基本理念是 “零開銷抽象”。理
運算符重載
Any和反射
rust數(shù)據(jù)庫操作
輸入輸出流
復合類型
性能測試

Deref

Derefderef 操作符 * 的 trait,比如 *v

一般理解,*v 操作,是 &v 的反向操作,即試圖由資源的引用獲取到資源的拷貝(如果資源類型實現(xiàn)了 Copy),或所有權(quán)(資源類型沒有實現(xiàn) Copy)。

Rust 中,本操作符行為可以重載。這也是 Rust 操作符的基本特點。本身沒有什么特別的。

強制隱式轉(zhuǎn)換(coercion)

Deref 神奇的地方并不在本身 解引 這個意義上,Rust 的設計者在它之上附加了一個特性:強制隱式轉(zhuǎn)換,這才是它神奇之處。

這種隱式轉(zhuǎn)換的規(guī)則為:

一個類型為 T 的對象 foo,如果 T: Deref<Target=U>,那么,相關(guān) foo 的某個智能指針或引用(比如 &foo)在應用的時候會自動轉(zhuǎn)換成 &U

粗看這條規(guī)則,貌似有點類似于 AsRef,而跟 解引 似乎風馬牛不相及。實際里面有些玄妙之處。

Rust 編譯器會在做 *v 操作的時候,自動先把 v 做引用歸一化操作,即轉(zhuǎn)換成內(nèi)部通用引用的形式 &v,整個表達式就變成 *&v。這里面有兩種情況:

  1. 把其它類型的指針(比如在庫中定義的,Box, Rc, Arc, Cow 等),轉(zhuǎn)成內(nèi)部標準形式 &v;
  2. 把多重 & (比如:&&&&&&&v),簡化成 &v(通過插入足夠數(shù)量的 * 進行解引)。

所以,它實際上在解引用之前做了一個引用的歸一化操作。

為什么要轉(zhuǎn)呢? 因為編譯器設計的能力是,只能夠?qū)?&v 這種引用進行解引用。其它形式的它不認識,所以要做引用歸一化操作。

使用引用進行過渡也是為了能夠防止不必要的拷貝。

下面舉一些例子:

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);

因為 String 實現(xiàn)了 Deref<Target=str>。

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);

因為 Rc<T> 實現(xiàn)了 Deref<Target=T>

fn foo(s: &[i32]) {
    // borrow a slice for a second
}

// Vec<T> implements Deref<Target=[T]>
let owned = vec![1, 2, 3];

foo(&owned);

因為 Vec<T> 實現(xiàn)了 Deref<Target=[T]>。

struct Foo;

impl Foo {
    fn foo(&self) { println!("Foo"); }
}

let f = &&Foo;

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

上面那幾種函數(shù)的調(diào)用,效果是一樣的。

coercion 的設計,是 Rust 中僅有的類型隱式轉(zhuǎn)換,設計它的目的,是為了簡化程序的書寫,讓代碼不至于過于繁瑣。把人從無盡的類型細節(jié)中解脫出來,讓書寫 Rust 代碼變成一件快樂的事情。