成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

揭開智能指針 Box 的神秘面紗

人工智能
Box<T> 會在堆上分配空間,存儲 T 值,并返回對應(yīng)的指針。同時 Box 也實現(xiàn)了 trait Deref 解引用和 Drop 析構(gòu),當 Box 離開作用域時自動釋放空間。

[[416792]]

本文轉(zhuǎn)載自微信公眾號「董澤潤的技術(shù)筆記」,作者董澤潤。轉(zhuǎn)載本文請聯(lián)系董澤潤的技術(shù)筆記公眾號。

熟悉 c++ 的肯定知道 shared_ptr, unique_ptr, 而 Rust 也有智能指針 Box, Rc, Arc, RefCell 等等,本文分享 Box 底層實現(xiàn)

Box <T>會在堆上分配空間,存儲 T 值,并返回對應(yīng)的指針。同時 Box 也實現(xiàn)了 trait Deref 解引用和 Drop 析構(gòu),當 Box 離開作用域時自動釋放空間

入門例子

例子來自 the rust book, 為了演示方便,去掉打印語句

  1. fn main() { 
  2.     let _ = Box::new(0x11223344); 

將變量 0x11223344 分配在堆上,所謂的裝箱,java 同學(xué)肯定很熟悉。讓我們掛載 docker, 使用 rust-gdb 查看匯編實現(xiàn)

  1. Dump of assembler code for function hello_cargo::main: 
  2.    0x000055555555bdb0 <+0>: sub    $0x18,%rsp 
  3.    0x000055555555bdb4 <+4>: movl   $0x11223344,0x14(%rsp) 
  4. => 0x000055555555bdbc <+12>: mov    $0x4,%esi 
  5.    0x000055555555bdc1 <+17>: mov    %rsi,%rdi 
  6.    0x000055555555bdc4 <+20>: callq  0x55555555b5b0 <alloc::alloc::exchange_malloc> 
  7.    0x000055555555bdc9 <+25>: mov    %rax,%rcx 
  8.    0x000055555555bdcc <+28>: mov    %rcx,%rax 
  9.    0x000055555555bdcf <+31>: movl   $0x11223344,(%rcx) 
  10.    0x000055555555bdd5 <+37>: mov    %rax,0x8(%rsp) 
  11.    0x000055555555bdda <+42>: lea    0x8(%rsp),%rdi 
  12.    0x000055555555bddf <+47>: callq  0x55555555bd20 <core::ptr::drop_in_place<alloc::boxed::Box<i32>>> 
  13.    0x000055555555bde4 <+52>: add    $0x18,%rsp 
  14.    0x000055555555bde8 <+56>: retq 
  15. End of assembler dump. 

關(guān)鍵點就兩條,alloc::alloc::exchange_malloc 在堆上分配內(nèi)存空間,然后將 0x11223344 存儲到這個 malloc 的地址上

函數(shù)結(jié)束時,將地址傳遞給 core::ptr::drop_in_place 去釋放,因為編譯器知道類型是 alloc::boxed::Box, 會掉用 Box 相應(yīng)的 drop 函數(shù)

單純的看這個例子,Box 并不神秘,對應(yīng)匯編實現(xiàn),和普通指針沒區(qū)別,一切約束都是編譯期行為

所有權(quán)

  1. fn main() { 
  2.     let x = Box::new(String::from("Rust")); 
  3.     let y = *x; 
  4.     println!("x is {}", x); 

這個例子中將字符串裝箱,其實沒必要這么寫,因為 String 廣義來講本身就是一種智能指針。這個例子會報錯

  1. 3 |     let y = *x; 
  2.   |             -- value moved here 
  3. 4 |     println!("x is {}", x); 
  4.   |                         ^ value borrowed here after move 

*x 解引用后對應(yīng) String, 賦值給 y 時執(zhí)行 move 語義,所有權(quán)不在了,所以后續(xù) println 不能打印 x

  1. let y = &*x; 

可以取字符串的不可變引用來 fix

底層實現(xiàn)

  1. pub struct Box< 
  2.     T: ?Sized, 
  3.     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global
  4. >(Unique<T>, A); 

上面是 Box 的定義,可以看到是一個元組結(jié)構(gòu)體,有兩個泛型參數(shù):T 代表任意類型,A 代表內(nèi)存分配器。標準庫里 A 是 Gloal 默認值。其中 T 有一個泛型約束 ?Sized, 表示在編譯時可能知道類型大小,也可能不知道,當然一般都用于不知道大小的場景,很少像上文一樣存儲 int

  1. #[stable(feature = "rust1", since = "1.0.0")] 
  2. unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> { 
  3.     fn drop(&mut self) { 
  4.         // FIXME: Do nothing, drop is currently performed by compiler. 
  5.     } 

這是 Drop 實現(xiàn),源碼里也說了,由編譯器實現(xiàn)

  1. #[stable(feature = "rust1", since = "1.0.0")] 
  2. impl<T: ?Sized, A: Allocator> Deref for Box<T, A> { 
  3.     type Target = T; 
  4.  
  5.     fn deref(&self) -> &T { 
  6.         &**self 
  7.     } 
  8.  
  9. #[stable(feature = "rust1", since = "1.0.0")] 
  10. impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> { 
  11.     fn deref_mut(&mut self) -> &mut T { 
  12.         &mut **self 
  13.     } 

實現(xiàn)了 Deref 可以定義解引用行為,DerefMut 可變解引用。所以 *x 對應(yīng)著操作 *(x.deref())

適用場景

官網(wǎng)提到以下三個場景,本質(zhì)上 Box 和普通指針區(qū)別不大,所以用處不如 Rc, Arc, RefCell 廣

  • 當類型在編譯期不知道大小,但代碼場景還要求確認類型大小的時候
  • 當你有大量數(shù)據(jù),需要移動所有權(quán),而不想 copy 數(shù)據(jù)的時候
  • trait 對象,或者稱為 dyn 動態(tài)分發(fā)常用在一個集合中存儲不同的類型上,或者參數(shù)指定不同的類型

官網(wǎng)有一個鏈表的實現(xiàn)

  1. enum List { 
  2.     Cons(i32, List), 
  3.     Nil, 

上面代碼是無法運行的,道理也很簡單,這是一種遞歸定義。對應(yīng) c 代碼也是不行的,我們一般要給 next 類型定義成指針才行

  1. enum List { 
  2.     Cons(i32, Box<List>), 
  3.     Nil, 
  4.  
  5. use crate::List::{Cons, Nil}; 
  6.  
  7. fn main() { 
  8.     let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); 

 

官網(wǎng)給的解決方案,就是將 next 變成了指針 Box , 算是常識吧,沒什么好說的

 

責任編輯:武曉燕 來源: 董澤潤的技術(shù)筆記
相關(guān)推薦

2015-08-20 13:43:17

NFV網(wǎng)絡(luò)功能虛擬化

2010-05-26 19:12:41

SVN沖突

2010-05-17 09:13:35

2021-06-07 08:18:12

云計算云端阿里云

2014-03-12 11:11:39

Storage vMo虛擬機

2009-06-01 09:04:44

Google WaveWeb

2018-03-01 09:33:05

軟件定義存儲

2009-09-15 15:34:33

Google Fast

2016-04-06 09:27:10

runtime解密學(xué)習(xí)

2023-11-02 09:55:40

2024-02-14 09:00:00

機器學(xué)習(xí)索引ChatGPT

2016-11-16 09:06:59

2025-01-07 15:07:13

2010-05-11 10:19:17

VMforceJava云計算

2017-10-16 05:56:00

2011-08-02 08:59:53

2021-07-28 21:49:01

JVM對象內(nèi)存

2021-09-17 15:54:41

深度學(xué)習(xí)機器學(xué)習(xí)人工智能

2020-04-14 10:44:01

區(qū)塊鏈滲透測試比特幣

2021-05-25 09:01:21

Linux命令Bash histor
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 中文字幕第一页在线 | 国产在线h | 欧美综合网| 偷拍亚洲色图 | 中文字幕在线三区 | 涩涩视频在线观看 | 欧美国产日韩在线观看成人 | 91干b| 欧美在线一区二区三区四区 | 国内自拍偷拍一区 | 国产亚洲精品精品国产亚洲综合 | 91日b| 日韩免费高清视频 | 日韩精品免费 | 人成久久 | 中文字幕亚洲一区 | 国产亚洲精品美女久久久久久久久久 | 国产精品18毛片一区二区 | 欧美视频免费在线观看 | 国产视频久久 | 成人在线电影网站 | 国产精品国产成人国产三级 | 久久精品日产第一区二区三区 | 久久国产精品一区二区 | 99免费精品视频 | 国产欧美日韩综合精品一区二区 | 一区二区三区电影在线观看 | 91电影 | 久久久久久国产 | 精品一区二区三区四区 | 日韩在线播放一区 | 福利影院在线看 | 欧美日韩第一页 | 国产一区二区久久 | 99热在线观看精品 | 先锋av资源网 | 中文字幕亚洲无线 | 久久精品久久久久久 | 欧美激情 一区 | 精品视频在线一区 | 国产精品久久久久无码av |