<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Rust中的智能指針:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak<T>

      Rust中的智能指針是什么

      智能指針(smart pointers)是一類數據結構,是擁有數據所有權和額外功能的指針。是指針的進一步發展

      指針(pointer)是一個包含內存地址的變量的通用概念。這個地址引用,或 ” 指向”(points at)一些其 他數據 。引用以 & 符號為標志并借用了他們所 指向的值。除了引用數據沒有任何其他特殊功能。它們也沒有任何額外開銷,所以在Rust中應用得最多。

      智能指針是Rust中一種特殊的數據結構。它與普通指針的本質區別在于普通指針是對值的借用,而智能指針通常擁有對數據的所有權。并且可以實現很多額外的功能。

      Rust智能指針有什么用,解決了什么問題

      它提供了許多強大的抽象來幫助程序員管理內存和并發。其中一些抽象包括智能指針和內部可變性類型,它們可以幫助你更安全、更高效地管理內存,例如Box<T> 用于在堆上分配值。Rc<T> 是一種引用計數類型,可以實現數據的多重所有權。RefCell<T> 提供內部可變性,可用于實現對同一數據的多個可變引用

      它們在標準庫中定義,可以用來更靈活地管理內存,智能指針的一個特點就是實現了Drop和Deref這兩個trait。其中Drop trait中提供了drop方法,在析構時會去調用。Deref trait提供了自動解引用的能力,讓我們在使用智能指針的時候不需要再手動解引用了

      Rust有哪些常用智能指針

      • Box<T>是最簡單的智能指針,它允許你在堆上分配值并在離開作用域時自動釋放內存。
      • Rc<T>Arc<T>是引用計數類型,它們允許多個指針指向同一個值。當最后一個指針離開作用域時,值將被釋放。Rc<T>不是線程安全的,而Arc<T>是線程安全的。

      內部可變性類型允許你在不可變引用的情況下修改內部值。Rust中有幾種內部可變性類型,包括Cell<T>RefCell<T>UnsafeCell<T>

      • Cell<T>是一個內部可變性類型,它允許你在不可變引用的情況下修改內部值。Cell<T>只能用于Copy類型,因為它通過復制值來實現內部可變性。
      • RefCell<T>也是一個內部可變性類型,它允許你在不可變引用的情況下修改內部值。與Cell<T>不同,RefCell<T>可以用于非Copy類型。它通過借用檢查來確保運行時的安全性。
      • UnsafeCell<T>是一個底層的內部可變性類型,它允許你在不可變引用的情況下修改內部值。與Cell<T>RefCell<T>不同,UnsafeCell<T>不提供任何運行時檢查來確保安全性。因此,使用UnsafeCell<T>可能會導致未定義行為。

      此外,Rust還提供了一種弱引用類型Weak<T>,它可以與Rc<T>Arc<T>一起使用來創建循環引用。Weak<T>不會增加引用計數,因此它不會阻止值被釋放。

      Box<T>

      Box<T>是最簡單的智能指針,它允許你在堆上分配值并在離開作用域時自動釋放內存。

      Box<T>通常用于以下情況:

      • 當你有一個類型,但不確定它的大小時,可以使用Box<T>來在堆上分配內存。例如,遞歸類型通常需要使用Box<T>來分配內存。
      • 當你有一個大型數據結構并希望在棧上分配內存時,可以使用Box<T>來在堆上分配內存。這樣可以避免棧溢出的問題。
      • 當你希望擁有一個值并只關心它的類型而不是所占用的內存時,可以使用Box<T>。例如,當你需要將一個閉包傳遞給函數時,可以使用Box<T>來存儲閉包。

      總之,當你需要在堆上分配內存并管理其生命周期時,可以考慮使用Box<T>

      下面是一個簡單的例子:

      fn main() {
          let b = Box::new(5);
          println!("b = {}", b);
      }
      復制代碼

      這里定義了變量 b,其值是一個指向被分配在堆上的值 5 的 Box。這個程序會打印出 b = 5;在這個例子 中,我們可以像數據是儲存在棧上的那樣訪問 box 中的數據。正如任何擁有數據所有權的值那樣,當像 b 這樣的 box 在 main 的末尾離開作用域時,它將被釋放。這個釋放過程作用于 box 本身(位于棧上) 和它所指向的數據(位于堆上)。

      但是Box<T>無法同時在多個地方對同一個值進行引用

      enum List { 
      Cons(i32, Box), 
      Nil, 
      } 
      use crate::List::{Cons, Nil}; 
      fn main() {
      let a = Cons(5, Box::new(Cons(10, Box::new(Nil)))); 
      let b = Cons(3, Box::new(a));
      let c = Cons(4, Box::new(a)); 
      }
      復制代碼

      編譯會得出如下錯誤: error[E0382]: use of moved value: a,因為b和c無法同時擁有a的所有權,這個時候我們要用Rc<T>

      Rc<T> Reference Counted 引用計數

      Rc<T>是一個引用計數類型,它允許多個指針指向同一個值。當最后一個指針離開作用域時,值將被釋放。Rc<T>不是線程安全的,因此不能在多線程環境中使用。

      Rc<T>通常用于以下情況:

      • 當你希望在多個地方共享數據時,可以使用Rc<T>。解決了使用Box<T>共享數據時出現編譯錯誤
      • 當你希望創建一個循環引用時,可以使用Rc<T>Weak<T>來實現。

      下面是一個簡單的例子,演示如何使用Rc<T>來共享數據:

      use std::rc::Rc;
      
      fn main() {
          let data = Rc::new(vec![1, 2, 3]);
          let data1 = data.clone();
          let data2 = data.clone();
          println!("data: {:?}", data);
          println!("data1: {:?}", data1);
          println!("data2: {:?}", data2);
      }
      復制代碼

      這個例子中,我們使用Rc::new來創建一個新的Rc<T>實例。然后,我們使用clone方法來創建兩個新的指針,它們都指向同一個值。由于Rc<T>實現了引用計數,所以當最后一個指針離開作用域時,值將被釋放。

      但是Rc<T>在多線程中容易引發線程安全問題,為了解決這個問題,又有了Arc<T>

      Arc<T> Atomically Reference Counted 原子引用計數

      Arc<T>是一個線程安全的引用計數類型,它允許多個指針在多個線程之間共享同一個值。當最后一個指針離開作用域時,值將被釋放。

      Arc<T>通常用于以下情況:

      • 當你希望在多個線程之間共享數據時,可以使用Arc<T>,是Rc<T>的多線程版本。
      • 當你希望在線程之間傳遞數據時,可以使用Arc<T>來實現。

      下面是一個簡單的例子,演示如何使用Arc<T>來在線程之間共享數據:

      use std::sync::Arc;
      use std::thread;
      
      fn main() {
          let data = Arc::new(vec![1, 2, 3]);
          let data1 = data.clone();
          let data2 = data.clone();
      
          let handle1 = thread::spawn(move || {
              println!("data1: {:?}", data1);
          });
      
          let handle2 = thread::spawn(move || {
              println!("data2: {:?}", data2);
          });
      
          handle1.join().unwrap();
          handle2.join().unwrap();
      }
      復制代碼

      這個例子中,我們使用Arc::new來創建一個新的Arc<T>實例。然后,我們使用clone方法來創建兩個新的指針,它們都指向同一個值。接著,我們在線程中使用這些指針來訪問共享數據。由于Arc<T>實現了線程安全的引用計數,所以當最后一個指針離開作用域時,值將被釋放。

      Weak<T> 弱引用類型

      Weak<T>是一個弱引用類型,它可以與Rc<T>Arc<T>一起使用來創建循環引用。Weak<T>不會增加引用計數,因此它不會阻止值被釋放。

      當你希望創建一個循環引用時,可以使用Rc<T>Arc<T>Weak<T>來實現。

      Weak<T>通常用于以下情況:

      • 當你希望觀察一個值而不擁有它時,可以使用Weak<T>來實現。由于Weak<T>不會增加引用計數,所以它不會影響值的生命周期。

      下面是一個簡單的例子,演示如何使用Rc<T>Weak<T>來創建一個循環引用:

      use std::rc::{Rc, Weak};
      
      struct Node {
          value: i32,
          next: Option<Rc<Node>>,
          prev: Option<Weak<Node>>,
      }
      
      fn main() {
          let first = Rc::new(Node { value: 1, next: None, prev: None });
          let second = Rc::new(Node { value: 2, next: None, prev: Some(Rc::downgrade(&first)) });
          first.next = Some(second.clone());
      }
      復制代碼

      這個例子中,我們定義了一個Node結構體,它包含一個值、一個指向下一個節點的指針和一個指向前一個節點的弱引用。然后,我們創建了兩個節點firstsecond,并使用Rc::downgrade方法來創建一個弱引用。最后,我們將兩個節點連接起來,形成一個循環引用。

      需要注意的是,由于Weak<T>不會增加引用計數,所以它不會阻止值被釋放。當你需要訪問弱引用指向的值時,可以使用upgrade方法來獲取一個臨時的強引用。如果值已經被釋放,則upgrade方法會返回None

      UnsafeCell<T>

      UnsafeCell<T>是一個底層的內部可變性類型,它允許你在不可變引用的情況下修改內部值。與Cell<T>RefCell<T>不同,UnsafeCell<T>不提供任何運行時檢查來確保安全性。因此,使用UnsafeCell<T>可能會導致未定義行為。

      由于UnsafeCell<T>是一個底層類型,它通常不直接用于應用程序代碼。相反,它被用作其他內部可變性類型(如Cell<T>RefCell<T>)的基礎。

      下面是一個簡單的例子,演示如何使用UnsafeCell<T>來修改內部值:

      use std::cell::UnsafeCell;
      
      fn main() {
          let x = UnsafeCell::new(1);
          let y = &x;
          let z = &x;
          unsafe {
              *x.get() = 2;
              *y.get() = 3;
              *z.get() = 4;
          }
          println!("x: {}", unsafe { *x.get() });
      }
      復制代碼

      這個例子中,我們使用UnsafeCell::new來創建一個新的UnsafeCell<T>實例。然后,我們創建了兩個不可變引用yz,它們都指向同一個值。接著,在一個unsafe塊中,我們使用get方法來獲取一個裸指針,并使用它來修改內部值。由于UnsafeCell<T>實現了內部可變性,所以我們可以在不可變引用的情況下修改內部值。

      需要注意的是,由于UnsafeCell<T>不提供任何運行時檢查來確保安全性,所以使用它可能會導致未定義行為。因此,在大多數情況下,你應該使用其他內部可變性類型(如Cell<T>RefCell<T>),而不是直接使用UnsafeCell<T>

      Cell<T>

      Cell<T>是一個內部可變性類型,它允許你在不可變引用的情況下修改內部值。Cell<T>只能用于Copy類型,因為它通過復制值來實現內部可變性。

      Cell<T>通常用于以下情況:

      • 當你需要在不可變引用的情況下修改內部值時,可以使用Cell<T>來實現內部可變性。
      • 當你需要在結構體中包含一個可變字段時,可以使用Cell<T>來實現。 下面是一個簡單的例子,演示如何使用Cell<T>來修改內部值:
      use std::cell::Cell;
      
      fn main() {
          let x = Cell::new(1);
          let y = &x;
          let z = &x;
          x.set(2);
          y.set(3);
          z.set(4);
          println!("x: {}", x.get());
      }
      復制代碼

      這個例子中,我們使用Cell::new來創建一個新的Cell<T>實例。然后,我們創建了兩個不可變引用yz,它們都指向同一個值。接著,我們使用set方法來修改內部值。由于Cell<T>實現了內部可變性,所以我們可以在不可變引用的情況下修改內部值。

      需要注意的是,由于Cell<T>通過復制值來實現內部可變性,所以它只能用于Copy類型。如果你需要在不可變引用的情況下修改非Copy類型的值,可以考慮使用RefCell<T>

      RefCell<T>

      RefCell<T>是一個內部可變性類型,它允許你在不可變引用的情況下修改內部值。與Cell<T>不同,RefCell<T>可以用于非Copy類型。

      RefCell<T>通過借用檢查來確保運行時的安全性。當你嘗試獲取一個可變引用時,RefCell<T>會檢查是否已經有其他可變引用或不可變引用。如果有,則會發生運行時錯誤。

      RefCell<T>通常用于以下情況:

      • 當你需要在不可變引用的情況下修改內部值時,可以使用RefCell<T>來實現內部可變性。

      • 當你需要在結構體中包含一個可變字段時,可以使用RefCell<T>來實現。

      下面是一個簡單的例子,演示如何使用RefCell<T>來修改內部值:

      use std::cell::RefCell;
      
      fn main() {
          let x = RefCell::new(vec![1, 2, 3]);
          let y = &x;
          let z = &x;
          x.borrow_mut().push(4);
          y.borrow_mut().push(5);
          z.borrow_mut().push(6);
          println!("x: {:?}", x.borrow());
      }
      復制代碼

      這個例子中,我們使用RefCell::new來創建一個新的RefCell<T>實例。然后,我們創建了兩個不可變引用yz,它們都指向同一個值。接著,我們使用borrow_mut方法來獲取一個可變引用,并使用它來修改內部值。由于RefCell<T>實現了內部可變性,所以我們可以在不可變引用的情況下修改內部值。

      需要注意的是,由于RefCell<T>通過借用檢查來確保運行時的安全性,所以當你嘗試獲取一個可變引用時,如果已經有其他可變引用或不可變引用,則會發生運行時錯誤。from劉金,轉載請注明原文鏈接。感謝!


       
      posted @ 2023-04-20 03:10  Pomelo_劉金  Views(728)  Comments(0)    收藏  舉報
      主站蜘蛛池模板: 国产成人午夜福利在线播放| 顶级少妇做爰视频在线观看| 晋宁县| 国产成人精品久久性色av| 久久亚洲精品天天综合网| 国产99在线 | 免费| 熟女视频一区二区在线观看| 欧美大胆老熟妇乱子伦视频| 国产午夜福利av在线麻豆| 国产高清在线精品一区不卡| 国产午夜精品理论大片| 久久精品国产免费观看频道| 5D肉蒲团之性战奶水欧美| 美女胸18大禁视频网站| 亚洲人精品午夜射精日韩| 99久re热视频这里只有精品6| 狂野欧美性猛交免费视频| 99热久久这里只有精品| 九九热热久久这里只有精品| 麻豆精品久久久久久久99蜜桃| 深夜av在线免费观看| 国产激情无码一区二区三区| 精品午夜久久福利大片| 国产精品自拍视频我看看| 亚洲第一无码AV无码专区| 久久国产国内精品国语对白| 亚洲成av人无码免费观看| 西西444www高清大胆| 国产成人午夜福利在线观看| 亚洲成A人片在线观看无码不卡| 久久青青草原精品国产app| 国产午夜精品福利免费不| 最新国产精品拍自在线观看| 香港日本三级亚洲三级| 亚洲一区二区三区人妻天堂| 亚洲日韩国产精品第一页一区| 久久精品国产免费观看频道| 亚洲综合精品一区二区三区| 亚洲中文久久久精品无码| 少妇伦子伦精品无吗| 无套内谢少妇高清毛片|