午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

Rust中的各種指針

 lichwoo 2021-07-05


Rust 中的指針大體可以分為以下四種:

  1. 引用 references

  2. “胖指針 fat pointers”(該分類存有爭議

  3. 智能指針 smart pointers

  4. 裸指針 raw pointers

1. 引用

就是直接對一個變量執(zhí)行 &、&mut 操作,永遠(yuǎn)不會為 null。
其占用的大小與 usize 一致。

與引用相關(guān)的一個名詞是 借用(borrowing)。
其定義為:將獲取引用作為函數(shù)參數(shù)稱為 借用(borrowing)

fn test_ref(){    let mut num = 5;    let num_ref = &mut num;    *num_ref = 100;    println!("{} sizeof &i32 {}", num, std::mem::size_of::<&i32>())    // output 100 sizeof &i32:8}

2. 胖指針

比引用多了些其它數(shù)據(jù)。
在 rust 中,屬于胖指針的數(shù)據(jù):切片( &[T] )。 T 為切片內(nèi)元素的類型。
切片類型存有: "地址(ptr) + 長度(len) "兩個字段。
圖中紅框內(nèi),就是一個切片。

fn test_fat_pointers(){    let mut arr = [1, 2, 3, 4];    let slice = &mut arr[1..4];    slice[0] = 100;    println!("{:?}", arr);   // [1, 100, 3, 4]    let slice = &arr[1..4];    println!("{:p} {:?}", slice, unsafe { transmute::<_, (usize, usize)>(slice) });    // Output: 0x8a6c0ff4ac (594518471852, 3)    //      0x8a6c0ff4ac 594518471852 這兩個值是相等的。    //      (594518471852, 3) 分別表示 具體數(shù)據(jù)的堆地址 和 長度 兩個字段。    //      注意這里是用 slice,而不是 &slice。(&slice表示這個變量本身的棧地址)    println!("sizeof &[i32]:{}", std::mem::size_of::<&[i32]>());    // Output: sizeof &[i32]:16    // 因?yàn)榘藘蓚€字段:地址 + 長度,所以其占用內(nèi)存為 2 個 usize 類型大小}

3. 智能指針

有特殊功能的,實(shí)現(xiàn)了 Deref、drop 相關(guān)的trait。

在 rust 中,屬于智能指針的數(shù)據(jù):String、 Vec<T>、Box、Cell、Rc 等等。

每一個智能指針的實(shí)現(xiàn)都不大一樣,這里就不再展開敘述。
僅以 Box 舉例:

fn test_smart_pointers(){    // 將本應(yīng)存在棧上的地址,存在了堆上    let mut num = Box::new(1);    // num_address 指向 box 里面的具體內(nèi)容(也就是儲存在堆上的數(shù)值 1)    let num_address : *mut i32 = &mut *num;    unsafe {        *num_address = 100    }    println!("{}", *num + 100)     // Output: 200}

4. 裸指針

類似 C 語言里面的指針,可以為 null !

創(chuàng)建裸指針,是 safe 的,讀寫裸指針,才需要 unsafe !

裸指針又可以分為可變、不可變,分別寫作 *mut T 和 *const T

這里的星號不是解引用運(yùn)算符,它是類型名稱的一部分。

這里的 T 表示指針指向的具體類型,裸指針本身的的類型大小與 usize 一致。

評論區(qū)有朋友指出:裸指針也能指向不定長類型,而且跟指向不定長類型的引用具有一樣的內(nèi)存布局。所以調(diào)用 sizeof,獲得的大小是原始類型的大小。
(不過指針這個變量本身的占用大小應(yīng)該還是 一個 usize)
詳見評論區(qū)的討論
fn test_raw_pointers(){    let mut num = 1;    // 將引用轉(zhuǎn)為裸指針    let num_raw_point = &mut num as *mut i32;    unsafe {        *num_raw_point = 100;        println!("{} {} {:p}", num, *num_raw_point, &num);         // Output: 100 100 0x8d8c6ff6bc    }    let address = num_raw_point as usize;    // 將一個 usize 對象,轉(zhuǎn)化為 裸指針    let raw = address as *mut i32;    unsafe {        *raw = 200;        println!("{} {} {:p} {}", num, *num_raw_point, &num, address);        // Output: 200 200 0x8d8c6ff6bc 607946536636    }}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多