自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

初識(shí)Rust語(yǔ)言的所有權(quán)概念

移動(dòng)開(kāi)發(fā) 開(kāi)發(fā)
初步探索火狐的東家Mozilla的新語(yǔ)言rust的所有權(quán)和借用概念,看看怎么在編譯期解決并發(fā)問(wèn)題的。

目前僅看了第二版的官方文檔,記錄一下初步印象,應(yīng)該還有更深刻一致的解釋,水平有限,僅供參考。
實(shí)驗(yàn)環(huán)境:ubuntu17.10,rust1.18,vscode1.14 + 擴(kuò)展rust(rls)。
BTW,環(huán)境搭建順利得令人意外,Rust工具鏈打造的簡(jiǎn)潔精美,原生支持git,安裝只需一條命令:curl https://sh.rustup.rs -sSf | sh。

初步印象

數(shù)據(jù)競(jìng)爭(zhēng)主要有三個(gè)條件:

  1. 兩個(gè)或更多指針同時(shí)訪問(wèn)同⼀數(shù)據(jù)。
  2. ⾄少有⼀個(gè)指針被寫⼊。
  3. 沒(méi)有同步數(shù)據(jù)訪問(wèn)的機(jī)制。

R非常重視并發(fā),根據(jù)官方介紹:Rust 是一門著眼于安全、速度和并發(fā)的編程語(yǔ)言。而并發(fā)需要解決的就是數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題,自然會(huì)非常重視數(shù)據(jù)的使用過(guò)程,說(shuō)是小心翼翼不為過(guò)。因?yàn)閿?shù)據(jù)要關(guān)聯(lián)到有名變量才能使用,所以rust在語(yǔ)言層面上針對(duì)變量的使用引入了解決方法,主要涉及的語(yǔ)法有:

  1. 變量聲明時(shí),不可變(immutable,默認(rèn))、可變(mutable)
  2. 變量賦值時(shí),所有權(quán)轉(zhuǎn)移(move)、借用(borrow)

需要注意的是,所有權(quán)僅針對(duì)復(fù)雜類型變量(在語(yǔ)法上,是沒(méi)有copy trait的類型),例如String、vect等在堆上存儲(chǔ)數(shù)據(jù)的類型,而簡(jiǎn)單類型并不用考慮,如int、tuple、array等,原因就在于賦值時(shí)數(shù)據(jù)是如何拷貝的(雖然都是淺拷貝)。

如果熟悉淺拷貝、深拷貝的概念,自然了解,對(duì)于在堆上分配空間的復(fù)雜類型,淺拷貝會(huì)導(dǎo)致兩個(gè)或更多變量/指針同時(shí)指向同⼀數(shù)據(jù),若有變量/指針作寫入操作,就會(huì)引起數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題。 

首圖

所以,Rust用可變/不可變、所有權(quán)、生命期等來(lái)破壞數(shù)據(jù)競(jìng)爭(zhēng)的條件,而這些解決方案全部在編譯期搞定!
當(dāng)然,代價(jià)是難以快速驗(yàn)證想法,畢竟使用變量時(shí)要仔細(xì)了,否則編都編不過(guò),期待***實(shí)踐和IDE的支持。

基本概念

1. 不可變、可變

let x = 3;  // x 默認(rèn)不可變
x = 4;  // 錯(cuò)誤!
let x = 4;  // 正確!遮蓋了原有的同名變量
let mut y = 3;  // y可變
y = 4;  // 正確!

2. 所有權(quán)轉(zhuǎn)移(move)

fn test(v: String) { println!("fn: {}", v); }  // 函數(shù)
let x = String::from("hello");  // 所有者x(String類型)
let y = x;  // 數(shù)據(jù)的所有權(quán)轉(zhuǎn)移給y!
let z = x; // 錯(cuò)誤!x已不可用
test(y);  // 所有權(quán)轉(zhuǎn)移,新的所有者是形參v!當(dāng)函數(shù)執(zhí)行完畢,v離開(kāi)作用域時(shí)值被丟棄(drop)!
println!("var: {}", y);  // 錯(cuò)誤!y已不可用

這難免有令人抓狂的感覺(jué),還能不能愉快地玩耍了?這數(shù)據(jù)跑得跟兔子一樣,想用的時(shí)候都不知道去哪了!還可能無(wú)意中跑到函數(shù)里直接躺尸!

3. 借用/引用(borrow)

那么,一個(gè)變量想多次使用怎么辦?答案是可以借用:使⽤其值但不獲取其所有權(quán)。

fn test1(v: String) { println!("fn: {}", v); } 
fn test2(v: &String) { println!("fn: {}", v); }  // 參數(shù)為引用類型
let s = String::from("hello");  // 所有者s(String類型)
let s1 = &s;  // 不可變借用(borrow)!
let s2 = &s;  // 借用
let s3 = s1;  // 借用
test2(s1);  // 借用
test1(*s1);  // 錯(cuò)誤!借用者s1沒(méi)有所有權(quán),無(wú)法通過(guò)s1轉(zhuǎn)移(cannot move out of borrowed content)。
println!("var: {}", s); // 正確

小結(jié):個(gè)人感覺(jué),所有權(quán)轉(zhuǎn)移主要為并發(fā)服務(wù),本身并不常用,畢竟數(shù)據(jù)經(jīng)常要復(fù)用,沒(méi)人樂(lè)意要一直提防著數(shù)據(jù)跑哪去了,尤其在函數(shù)調(diào)用時(shí)。既然如此,一般把所有者保持不變,多使用引用,主要體現(xiàn)在復(fù)雜數(shù)據(jù)結(jié)構(gòu)和函數(shù)上。

進(jìn)一步

但是,實(shí)際使用的情況會(huì)比較復(fù)雜,即是否可變與轉(zhuǎn)移、借用三者相互影響(混用)的情況。
從數(shù)據(jù)競(jìng)爭(zhēng)的角度:讀讀不沖突,但讀寫、寫寫會(huì)沖突(讀即不可變,寫即可變);從實(shí)現(xiàn)的角度:引用是基于所有權(quán)的。
因此,可以看看哪些對(duì)象會(huì)沖突:(所有者,引用) × (不可變,可變) 

首先,是否可變和所有權(quán)沒(méi)有關(guān)系。

let x = String::from("hello");
let mut z = x;  // 轉(zhuǎn)移后變量x不可用
z.push_str(" z");  //正確
// 可變引用要用星號(hào)來(lái)獲得引用的內(nèi)容,不可變引用不需要。
let mut x = 5; 
let y = &mut x;
*y += 1;

 

雖然不可變引用(&T)沒(méi)有所有權(quán),不會(huì)導(dǎo)致值被誤轉(zhuǎn)移,但借用之時(shí)要求值不能變,這意味著此時(shí):所有權(quán)不能轉(zhuǎn)移、所有者不能改值、不能同時(shí)有可變引用!

let mut x = String::from("hello");
let y = &x;  // 不可變引用
let z = x;  // 錯(cuò)誤
x.push_str(" x");  // 錯(cuò)誤
let z = &mut x;  // 錯(cuò)誤:可變引用

 

可變引用(&mut T)

可變引用使用上略復(fù)雜,概念上也沒(méi)有太統(tǒng)一的理解,這里單獨(dú)考查。
“可變權(quán)”即可變引用對(duì)數(shù)據(jù)的讀寫權(quán),具有唯一性(只有一個(gè)可用的可變引用)和獨(dú)占性(其它讀、寫統(tǒng)統(tǒng)無(wú)效),所以對(duì)編譯影響相當(dāng)大??勺円玫目勺儥?quán)和所有者對(duì)數(shù)據(jù)的所有權(quán)有相似性,因?yàn)榭勺儥?quán)也有move行為。

注:官方文檔里沒(méi)有可變權(quán)的概念,但個(gè)人感覺(jué),用這個(gè)概念比較好理解可變引用的使用,也許還有更本質(zhì)的解釋,特此說(shuō)明。

可變權(quán)move的兩種方式

let mut x = String::from("hello");  // 所有者x有可變權(quán)
// 1. 直接轉(zhuǎn)移
let y = &mut x;  // 1. y為可變引用,可變權(quán)move自x
let z = y;  // 直接轉(zhuǎn)移。z為可變引用
y.push_str(" y");  // 錯(cuò)誤!y的可變權(quán)已move給z
z.push_str(" z");  // 正確
// 2. 間接轉(zhuǎn)移
let mut y = &mut x;  // 2. y為可變引用,可變權(quán)move自x
let w = &mut y;  // 要求y可變。w為可變引用
w.push_str(" w");  // 正確
// 轉(zhuǎn)移(函數(shù))
fn test(i: &mut String) { 
  i.push_str(" i");   // 正確
}
let mut x = String::from("hello");  // 所有者x有可變權(quán)
test(&mut x);
x.push_str(" x");  // 正確!可變權(quán)已歸還

 

可變引用若有寫入操作則要求所有者可變。

let x = String::from("hello");  // x不可變
let mut z = &x;   // z為不可變引用
z.push_str(" z");  // 錯(cuò)誤!
let w = &mut z;  // w為可變引用
w.push_str(" w");  // 錯(cuò)誤!
let mut y = x;  // 所有權(quán)轉(zhuǎn)移,y可變
let z = &mut y;   // z為可變引用,要求y可變
z.push_str(" z");  // 正確!
let w = &z;  // w 為不可變引用
w.push_str(" w");  // 錯(cuò)誤!

 

總結(jié):

因?yàn)槎忌婕暗街档男薷?,可變引用的行為和所有者相似,而且可變?quán)和所有權(quán)都是面向數(shù)據(jù)且唯一的。

所有者

  1. 有所有權(quán),move后不再可用,當(dāng)所有者生命期結(jié)束,值被丟棄。
  2. 讀的時(shí)候類似不可變引用,寫的時(shí)候類似可變引用。

可變引用(&mut T)

  1. 有可變權(quán),move自被引用者,當(dāng)可變引用生命期結(jié)束,可變權(quán)自動(dòng)歸還。
  2. 可變權(quán)的源頭應(yīng)該來(lái)自所有者,否則意義不大。

參考

  1. Rust 環(huán)境配置事項(xiàng)一覽
  2. 官方文檔:Rust 程序設(shè)計(jì)語(yǔ)言(第二版)
  3. Rust教程11之所有權(quán)
  4. 你在開(kāi)發(fā)過(guò)程中都遇到過(guò) Rust 的哪些坑?
責(zé)任編輯:張子龍 來(lái)源: 開(kāi)源中國(guó)社區(qū)
相關(guān)推薦

2024-03-19 14:43:55

Rust編譯所有權(quán)

2024-01-10 09:26:52

Rust所有權(quán)編程

2022-08-11 10:42:58

Rust

2024-09-02 10:40:18

2024-04-24 12:41:10

Rust安全性內(nèi)存

2022-03-18 08:00:00

區(qū)塊鏈代幣以太坊

2011-01-07 09:19:35

Linux文件權(quán)限

2021-07-30 05:12:54

智能指針C++編程語(yǔ)言

2013-08-16 10:46:20

2022-05-30 00:19:13

元宇宙NFTWeb3

2022-11-03 15:14:43

Linux文件權(quán)限

2009-11-28 20:21:14

2018-01-23 11:15:28

云計(jì)算數(shù)據(jù)平臺(tái)云平臺(tái)

2011-01-20 07:50:51

Linux文件系統(tǒng)管理所有權(quán)

2018-12-14 10:08:23

物聯(lián)網(wǎng)訂閱IOT

2017-10-23 12:42:42

2009-09-12 09:46:47

Windows 7所有權(quán)添加

2020-09-09 09:19:00

SpringSecurity權(quán)限

2010-07-20 17:36:55

SQL Server

2013-06-14 10:34:34

iOS App蘋果iOS開(kāi)發(fā)者
點(diǎn)贊
收藏

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