欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:Rust學(xué)習(xí)筆記(一)

柚子快報(bào)邀請(qǐng)碼778899分享:Rust學(xué)習(xí)筆記(一)

http://yzkb.51969.com/

參考文獻(xiàn)1:https://course.rs/first-try/installation.html

參考文獻(xiàn)2:rust-based-os-comp2024/2024-spring-scheduling-1.md at main · LearningOS/rust-based-os-comp2024 · GitHub

使用wsl2 ubuntu 20.04,照著教程直接

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

?然后無(wú)腦回車安裝完成。

基礎(chǔ)1 牛刀小試

cargo new # 創(chuàng)建新項(xiàng)目(自動(dòng)git)

cargo run # 直接編譯運(yùn)行,可添加--release生成高性能代碼

cargo build # 先編譯,可添加--release生成高性能代碼

./target/debug/ # 運(yùn)行可執(zhí)行文件

cargo check # 在不編譯的情況下快速檢查能否編譯通過(guò)【神器】,但比Go差太遠(yuǎn)

Cargo.toml:項(xiàng)目描述,跟package.xml差不多。

依賴直接以如下形式給出:

[dependencies]

rand = "0.3" # 官方包,只需指定版本

hammer = { version = "0.5.0"} # 指定版本的另一種方法

color = { git = "https://github.com/bjz/color-rs" } # 網(wǎng)上的包,指定url

geometry = { path = "crates/geometry" } # 本地的包,指定文件路徑

Cargo.lock:根據(jù)toml生成的項(xiàng)目以來(lái)詳細(xì)清單,基本不需要手動(dòng)修改。

基礎(chǔ)2 Rust入門(亂序筆記,建議跳過(guò))

let綁定的變量不可變,let mut的可變,并且可以一個(gè)let賦多個(gè)值。

我秉承實(shí)用主義解釋方法,rust的話術(shù)后面深入了解之后再接受。

let {mut} : { = };

let ({mut} , {mut} , ...): (, , ...){ = (, , ...)};

這多個(gè)值實(shí)際上構(gòu)成了一個(gè)復(fù)雜變量,但可以單獨(dú)使用。這種隨地湊出向量的搞法比較優(yōu)雅。

下劃線開頭的變量不會(huì)因?yàn)槲词褂枚痪妗?/p>

定義成mut但沒(méi)變過(guò)的變量會(huì)被警告。

非常古典的類型名,i32、f64這種。

后定義的同名變量會(huì)把之前的覆蓋,且不會(huì)報(bào)警。

數(shù)字可以在后面加上下劃線(也可以不加)+類型規(guī)定為對(duì)應(yīng)類型的數(shù)字。

序列用法:

1..5 // 代表1~4

1..=5 // 代表1~5

// 字符也可以用

fn func(var: type, ...) {

let x = {

let y = 3;

y * 2

};

x + 3

}

不加分號(hào)的表達(dá)式會(huì)返回一個(gè)值,可以作為函數(shù)返回值,也可以作為語(yǔ)塊表達(dá)式返回值。

if-else語(yǔ)塊也可以返回值,可以用來(lái)賦值。

Rust也可以用return,只不過(guò)可以不用。

let x = 5;

let y = x; // 直接拷貝值

let x = String::from("Hello"); // 堆上分配內(nèi)存,創(chuàng)建String對(duì)象

let y = x; // 把x綁定的值的所有權(quán)移交給y,x被廢黜

let x: &str = "Hello"; // 字符串字面量只讀,放在靜態(tài)數(shù)據(jù)區(qū)域,此處的x只是一個(gè)引用

let y = x; // 相當(dāng)于x是一個(gè)指針,然后指針值拷貝給了x

基本類型注意:

let a = [1, 1, 4, 5, 1, 4]; // 用.len()獲取數(shù)組長(zhǎng)度

let b = &a[2..4]; // 切片以引用的方式獲取,注意左開右閉。左右界限均可以省略。

let c = (1, 1, 4, 5); // 用c.2獲取第3個(gè)數(shù)

let v = vec![10, 20, 30, 40]; // 宏定義向量

for e in v.iter_mut() { // 要允許值可變,要用iter_mut()

*e *= 2; // 用的是引用值,要用*解引用?

}

v.iter().map(|element| { // 對(duì)迭代器中每個(gè)元素應(yīng)用一個(gè)匿名函數(shù)

element << 1

}).collect() // 將迭代器的結(jié)果收集起來(lái)組成新的集合

fn main() {

let vec0 = Vec::new();

let mut vec1 = fill_vec(vec0);

println!("{} has length {}, with contents: `{:?}`", "vec0", vec0.len(), vec0);

vec1.push(88);

println!("{} has length {}, with contents `{:?}`", "vec1", vec1.len(), vec1);

}

fn fill_vec(vec: Vec) -> Vec {

// 這里把vec0的數(shù)據(jù)借調(diào)了,所以vec0訪問(wèn)不了。所以上面的fill_vec得是深拷貝。

let mut vec = vec;

vec.push(22);

vec.push(44);

vec.push(66);

vec

}

結(jié)構(gòu)體的clone方法需要額外#[derive(Clone)]才能使用。

用impl <結(jié)構(gòu)體名>來(lái)定義方法。

需要用&的情景:

借用數(shù)據(jù),實(shí)際上相當(dāng)于取地址。要使用數(shù)據(jù)(比如算術(shù)運(yùn)算)時(shí)需要加*解引用,但是rust居然會(huì)自己解引用。感覺這個(gè)設(shè)計(jì)非常nt,落了下乘。也許我后面會(huì)理解的吧。避免數(shù)據(jù)復(fù)制(傳遞復(fù)雜數(shù)據(jù)結(jié)構(gòu)的引用)共享不可變數(shù)據(jù)可變引用&mut:每個(gè)數(shù)據(jù)同一時(shí)間只能有一個(gè)&mut存在,而且被引用的必須是mut變量。參數(shù)中用&可以避免擁有數(shù)據(jù)所有權(quán),特別是在只需要讀取的時(shí)候。其實(shí)還是傳地址,只是rust會(huì)自己解引用。

rust的枚舉類型可以定義:

結(jié)構(gòu)體變體,即不加struct前綴的三種結(jié)構(gòu)體方法,跟struct類似,要用impl在外面定義用Nested(<其他枚舉類型>)進(jìn)行嵌套枚舉

match的標(biāo)準(zhǔn)用法:

fn process_message(msg: Message) {

match msg {

Message::Quit => println!("Quit message"),

Message::ChangeColor(r, g, b) => {

println!("Change color to RGB({}, {}, {})", r, g, b);

}

Message::Move { x, y } => {

println!("Move to ({}, {})", x, y);

}

}

}

let a = "test";

let b = a.to_string(); // 字符串字面量轉(zhuǎn)String

let a = String::from("test");

let b = &a; // String轉(zhuǎn)字符串字面量:直接引用地址

不允許let mut (l, r) = (0, 0);,非常抽象。

調(diào)用成員方法的時(shí)候會(huì)自動(dòng)解引用,與是否是函數(shù)參數(shù)無(wú)關(guān)。&會(huì)直接作用于調(diào)用過(guò)方法后的整體。

字符串操作:

let s = String::from("test");

// 遍歷:直接得到字符值

for c in s.chars() {

if c == ' ' {

break;

}

}

s.replace(<要替換的字符串>, <要換成的字符串>);

s.replacen(<要替換的字符串>, <要換成的字符串>, <替換數(shù)目>);

// 只要有一個(gè)String類型,其他的即使是&str也可以相加

不加pub全是隱藏,包括use。

序列要遍歷需要.iter(),但hashmap遍歷不需要,自身就是一個(gè)集合。

遇到任何不需要轉(zhuǎn)移值的地方都要打&。

Some()把一個(gè)變量變成optional變量。

if let和match都是模式匹配的方法。

如果被匹配的option變量在模式匹配后還要使用,那么不能夠使用Some(v),而是要使用Some(ref v),避免所有權(quán)被奪走。

拋出錯(cuò)誤用Err(String),不拋出用Ok(String),返回值都是Result<成功時(shí)返回的類型,錯(cuò)誤時(shí)返回的類型>。

parse自己返回值就是Result類型。

?很厲害,對(duì)于返回Result的,如果Err就立刻返回Err,如果有值就取出值,繼續(xù)執(zhí)行;對(duì)于返回Option的,如果None就立刻返回None,如果有值就解出Some(v)的v,繼續(xù)執(zhí)行。

但使用?的函數(shù)必須是Result返回值,包括main本身。在非錯(cuò)誤情形下,要調(diào)用Ok(())來(lái)返回一個(gè)空單元。

?遇到錯(cuò)誤或None會(huì)立刻返回,但Err并不會(huì),后續(xù)的代碼會(huì)繼續(xù)執(zhí)行。

注意:只有函數(shù)結(jié)束時(shí)的表達(dá)式才能作為返回值。

用Result>裝各種錯(cuò)誤。

泛型寫法:

struct泛型直接在名字后面跟<>impl Struct {}里面的函數(shù)名字后面不用跟<>,調(diào)用的時(shí)候Struct::method()完全不用寫,大概是都可以自己推斷?

trait感覺像C++的虛函數(shù),聲明但不實(shí)現(xiàn)。trait xxx由后面的impl xxx for type來(lái)實(shí)現(xiàn)。

但是trait似乎是任何對(duì)象都可以通用的,作為公共的.xxx()接口。

self是當(dāng)前對(duì)象,Self是當(dāng)前類型。

trait的默認(rèn)函數(shù)跟C++虛函數(shù)一樣,可以在聲明虛函數(shù)處定義默認(rèn)操作。

若只關(guān)心對(duì)象是否有特定trait,只需把對(duì)象類型寫成impl 即可。比較靈活。

要是關(guān)心對(duì)象是否有多個(gè)特定trait,只需一個(gè)impl,后面把trait名稱用+連起來(lái)即可。

用#[should_panic(expected = "...")]捕獲panic信息,使得panic不顯示。即“預(yù)料之中的panic”。

unsafe操作:用unsafe <不安全函數(shù)定義>或者unsafe{<不安全運(yùn)算/函數(shù)調(diào)用>},一般把&mut用as轉(zhuǎn)成*mut使用。例程:

unsafe fn modify_by_address(address: usize) {

unsafe {

let ptr = address as *mut u32;

*ptr = 0xAABBCCDD;

}

}

#[cfg(test)]

mod tests {

use super::*;

#[test]

fn test_success() {

let mut t: u32 = 0x12345678;

unsafe { modify_by_address(&mut t as *mut u32 as usize) };

assert!(t == 0xAABBCCDD);

}

}

也可以用::into_raw()生成裸指針,然后用::from_raw()解引用。不過(guò)這個(gè)應(yīng)該需要derive?

#[cfg(<邏輯表達(dá)式>)] 實(shí)際上就是條件編譯。

cargo:rustc-env=<環(huán)境變量名>=<值> # 定義環(huán)境變量

cargo:rustc-cfg=<屬性名>{=<值>} # 相當(dāng)于define,值可以省略

extern引入的函數(shù)默認(rèn)是unsafe的,

extern "" {

;

...

}

相關(guān)的函數(shù)attribute

#[no_mangle] // 不讓外部函數(shù)覆蓋本地函數(shù)名稱

#[link_name = "xxx"] // 讓這個(gè)外部函數(shù)在本地可以用xxx的名字被調(diào)用

生命周期標(biāo)記:'<字母和數(shù)字的組合,或是下劃線>。一般來(lái)說(shuō)'a、'b這一類就夠用了。

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str // 讓函數(shù)參數(shù)和返回值的生命周期一致

fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str // 讓返回值和第一個(gè)參數(shù)的生命周期一致

rust里的花括號(hào)不能亂加,因?yàn)樽饔糜蚝蜕芷趶?qiáng)綁定。

對(duì)于形如

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {

if x.len() > y.len() {

x

} else {

y

}

}

fn main() {

let string1 = String::from("long string is long");

let result;

{

let string2 = String::from("xyz");

result = longest(string1.as_str(), string2.as_str());

}

println!("The longest string is '{}'", result);

}

造成的生命周期不統(tǒng)一問(wèn)題只能靠移動(dòng)string2或者println!來(lái)實(shí)現(xiàn),非常抽象。

struct Book<'a> {

++++

author: &'a str,

++

title: &'a str,

++

}

fn main() {

let name = String::from("Jill Smith");

let title = String::from("Fish Flying");

let book = Book { author: &name, title: &title };

// 此后未再用過(guò)name和title,于是name和title的符號(hào)被連同數(shù)據(jù)一起銷毀

// 然而它們的數(shù)據(jù)還會(huì)被book使用,所以要讓author和title的生命周期跟book一樣長(zhǎng)

// 即,author和title借來(lái)的數(shù)據(jù)不會(huì)在name和title的銷毀時(shí)失去

println!("{} by {}", book.title, book.author);

}

一個(gè)典型的vec操作:

fn main() {

let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"];

let mut my_iterable_fav_fruits = my_fav_fruits.iter(); // TODO: Step 1

assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana"));

assert_eq!(my_iterable_fav_fruits.next(), Some(&"custard apple")); // TODO: Step 2

assert_eq!(my_iterable_fav_fruits.next(), Some(&"avocado"));

assert_eq!(my_iterable_fav_fruits.next(), Some(&"peach")); // TODO: Step 3

assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry"));

assert_eq!(my_iterable_fav_fruits.next(), None); // TODO: Step 4

}

需要注意的是,一個(gè).iter()得到的迭代器是空頭的,即,要再next()一下才得到第一個(gè)元素。

沙比String只能+= &str,不能加String。感覺跟shell語(yǔ)言有相似之處,等號(hào)右側(cè)使用的實(shí)際上是$var而不是var。

enum里的結(jié)構(gòu)體要用::<結(jié)構(gòu)體名> {構(gòu)造}來(lái)引用,而不是(<結(jié)構(gòu)體名> { .. })。

注意以下區(qū)別:

for ref x in set.iter() = for x in set.iter()

for mut x in set.iter() // 這種寫法沒(méi)用

for x in set.iter_mut() // 這才是正確的

這里面的x是迭代器,即&,直接調(diào)用x.method()會(huì)自動(dòng)解引用,但調(diào)用函數(shù)得用func(*x)。

不用for/while,純用迭代器遍歷有以下幾種方法:

let mut vec = Vec::new();

let mut map = HashMap::new();

// for_each,此處寫兩種,以下只寫vec

vec.iter().for_each(|element| {

<執(zhí)行操作>

});

map.iter().for_each(|(key, value)| {

<執(zhí)行操作>

});

vec.iter().map(|element| {

<執(zhí)行操作>

element

}).collect(); // 執(zhí)行體返回element的話相當(dāng)于消耗了vec之后又得到一個(gè)vec

vec.iter().inspect(|&element| {

<執(zhí)行操作>

}).count(); // 執(zhí)行count來(lái)消費(fèi)迭代器

// 對(duì)于字符串是string.chars()而不是iter(),后面差不多

最好用的還是for_each。

thread::spawn(|| {})借用外部變量,thread::spawn(move || {})獲取外部變量所有權(quán)。

spawn返回handle,handle.join()跟蹤線程,并獲取Result形式的返回值。

let a = Arc::new(value); // 創(chuàng)建線程安全的共享變量

let b = Arc::new(Mutex::new(value)); // 創(chuàng)建線程安全的共享互斥變量

let c = a.lock().unwrap(); // 互斥變量只有l(wèi)ock了才能確定,共享變量必須unwrap

for x in xxx.iter()和for x in &xxx是等效的,不過(guò)傳出來(lái)的東西有點(diǎn)區(qū)別。?

定義結(jié)構(gòu)體的時(shí)候可以類型名挨著,但是調(diào)用的時(shí)候中間全都得加上::。

幾種智能指針:

let a = <值>;

let shared_a = Arc::new(a); // 生成線程安全變量,并奪權(quán)

let thread_a = Arc::clone(&shared_a); // 對(duì)每個(gè)線程生成單獨(dú)的變量

// 一般來(lái)說(shuō),只有.clone()和傳引用可以不奪權(quán),其余的都會(huì)奪權(quán)。

// Box = unique_ptr in C++

enum List {

Cons(i32, Box),

Nil

} // Box可以允許嵌套定義

let a = Box::new(<值>);

println!("{}", *a); // 相當(dāng)于生成值對(duì)應(yīng)的指針,并且會(huì)自動(dòng)釋放

// Box相當(dāng)于是Rust的常用指針

// Box用于定義或聲明,Box::::..用于調(diào)用

let a = Cow::new(<變量>); // 直接奪權(quán)

let b = Cow::new(<引用>); // 借用,如果經(jīng)由b想要修改數(shù)據(jù),則奪權(quán)

// Rc = shared_ptr in C++

let a = Rc::new(<變量>); // 創(chuàng)建共享變量

let b = Rc::clone(&a); // 指向同一個(gè)變量

println!("{}", Rc::strong_count(&a)); // 輸出引用計(jì)數(shù)

宏定義:

macro_rules! my_macro {

() => {

println!("Check out my macro!");

}; // 不同分支之間要用分號(hào)隔開

($val:expr) => {

println!("Look at this other macro: {}", $val);

}

}

可以定義在module里,宏上方寫#[macro_export],然后在外面直接用my_macro!()調(diào)用。

Clippy很強(qiáng),多用。

as可以用來(lái)轉(zhuǎn)換類型,也可以用來(lái)改變引進(jìn)的包名。

寫類型轉(zhuǎn)換:

use std::convert::{TryFrom, TryInto};

impl TryFrom<源類型> for 目標(biāo)類型 {

fn try_from(參數(shù): 源類型) -> Result {

...

}

}

let a = 目標(biāo)類型::try_from(源類型對(duì)象);

let b: Result<目標(biāo)類型, _> = 源類型對(duì)象.try_into(); // 允許失敗的嘗試類型轉(zhuǎn)換,可以不寫impl

對(duì)于泛型函數(shù),用>來(lái)在函數(shù)中使用as_ref(),用>來(lái)在函數(shù)中使用as_mut()。這兩種方法同時(shí)限制了泛型類型,因?yàn)槔鏏sRef只有str類型有。

From/Into只需要定義其一就夠了,TryFrom/TryInto同理。只是From/Into不會(huì)處理出錯(cuò)情況。

雜亂無(wú)章的知識(shí)學(xué)習(xí)結(jié)束了,接下來(lái)是算法部分。

基礎(chǔ)3 算法實(shí)現(xiàn)

其實(shí)主要是數(shù)據(jù)結(jié)構(gòu),大部分算法所有語(yǔ)言都差不多。

冒泡排序:

fn sort(array: &mut [T]){

//TODO

let n = array.len();

for i in 0..n {

for j in i + 1..n {

if array[i] > array[j] {

// 單純的變量交換和數(shù)組元素交換略有不同,前者第三步可以靠重新綁定tmp的值來(lái)

// 完成,不需要克隆兩次,但array[j]不能let重綁定。

let tmp = array[i].clone();

array[i] = array[j].clone();

array[j] = tmp;

}

}

}

}

柚子快報(bào)邀請(qǐng)碼778899分享:Rust學(xué)習(xí)筆記(一)

http://yzkb.51969.com/

精彩鏈接

評(píng)論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19428347.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄