Rust 基本語法

變量

整數

  • 無符號整數以u開頭
  • 有符號整數以i開頭
  • 對于Rust默認整數是i32
  • 對于整數溢出
    • 開發模式中編譯會檢測溢出,如果溢出會導致程序panic
    • 發布模式中編譯不會檢查可能會導致的溢出,如果運行時發生溢出,會執行環繞操作保證數值在范圍內且程序不會panic

單精度浮點類型

  • f32

雙精度浮點類型

  • f64
  • Rust采用f64作為默認的浮點類型

布爾類型

  • bool:占用1字節大小

字符類型

  • char:占用4字節大小
  • 使用單引號

復合類型

  • 元組(Tuple):可以將多個類型的多個值放在一個類型里,長度固定一旦創建無法修改
    • 創建:在小括號中,將值用逗號分開
    • Tuple中的每一個位置都對應一個類型,Tuple中各元素的類型不必相同
    • 訪問Tuple元素使用 .下標 進行訪問
  • 數組:數組元素類型必須相同,數組長度固定,在棧上存儲
    • 創建:在中括號中,將值用逗號分開
    let a:[i32; 5] = [1, 2, 3, 4, 5];
    let a = [3; 5];// 等于let a = [3, 3, 3, 3, 3];
    
    • 使用 [下標] 訪問數組元素
    • 下標越界編譯會通過,但是運行會panic

字符串

  • String在堆內存上分配,能夠存儲在編譯時未知數量的文本
  • String類型的值可以修改,但是字符串字面值不能修改,因為字符串字面值在編譯時就知道它的內容了,其文本內容直接被硬編碼到最終的可執行文件里(速度快,高效,是因為它的不可變性),對于String類型,為了支持可變性,需要在堆內存上分配內存來保存編譯時未知的文本內容(操作系統必須在運行時來請求內存,這步通過調用String::from來實現,當用完String后,需要使用某種方式將內存返回給操作系統)
let mut s = String::from("abcdefg");
s.push_str("hi");
// s -> abcdefghi
  • 一個String由三個部分組成(這部分存放在棧中,字符串內容存放在堆中)
    • 指向內容的指針
    • 長度(存放字符串內容所需的字節數)
    • 容量(從操作系統獲得的總字節數)
let s1 = String::from("123");
let s2 = s1;
// s1將不能再被使用
let s1 = String::from("123");
let s2 = s1.clone();
// s1和s2獨立

Copy trait

  • 如果一個類型實現了Copy這個trait,那么舊的變量在賦值后任然可以使用
  • 如果一個類型或者該類型的一部分實現了Drop trait,那么Rust不允許讓它再去實現Copy trait了

一些擁有Copy trait的類型

  • 任何簡單標量的組合類型都可以是Copy的
  • 任何需要分配內存或者某種資源的都不是Copy的
  • 一些擁有Copy trait的類型:
    • 所有的整數類型,例如u32
    • bool
    • char
    • 所有的浮點類型
    • Tuple(元組)要求其所有字段都是Copy的

函數

聲明

使用 fn 關鍵字
Rust命名規范(snake case):

  • 針對函數和變量名,所有字母都是小寫,單詞之間使用下劃線分開

參數

  • 在函數簽名里,必須聲明每個參數的類型

語句/表達式

  • 函數體由一系列語句組成,可選的由一個表達式結束
  • Rust是一個基于表達式的語言
  • 語句是執行一些動作的指令
  • 表達式會計算產生一個值
  • 函數的定義也是語句
  • 語句沒有返回值,所以不可以使用let將一個語句賦給一個變量
// 塊表達式
let y = {let x = 1;x + 3
}
// y等于塊表達式最后一個值即x + 3 = 4
// 如果x + 3后加上分號,那么x + 3就變成語句了,分號后面沒有返回值,默認就是空的Tuple即()
fn f() -> i32{5
}fn main(){let res = f();// res為5
}

返回值

  • -> 符號后邊聲明函數返回值的類型,但是不可以為返回值命名
  • 在Rust里面,返回值就是函數體最后一個表達式的值
  • 若想提前返回,需使用 return 關鍵字,并指定一個值
  • 大多數函數都是默認使用最后一個表達式作為返回值

注釋

  • 單行注釋
// 這是單行注釋
  • 多行注釋
// 這是
// 多行注釋/*** 這是* 多行注釋
**/

控制流

if表達式

  • if 表達式 的條件必須是bool類型,否則會報錯(Rust不會自動類型轉換)
if 3 < 5{// true
}else{// false
}
let a = if 1 < 3 { 1 } else { 6 };
// a = 1;

loop表達式

  • loop表達式里的代碼會一直循環執行,直到break
let mut cnt = 0;
let res = loop{cnt += 1;if cnt == 10 {break cnt;}
}
// res = 10;

while循環

let mut cnt = 100;
while cnt > 0 {cnt -= 1;
}
// res = 0;

for循環

  • 安全,簡潔,用得較多
let a = [1, 2, 3, 4];for tem in a.iter() {println!("{}", tem);
}

Range

  • 標準庫提供
  • 指定開始數字和結束數字,Range可以生成他們之間的數字(不含結束)
  • rev方法可以反轉Range
// (1..4)生成1 - 3 之間的數字
// rev()反轉,即 3 - 1之間的數字
// 輸出 3 2 1
for tem in (1..4).rev() {println!("{}", tem);
}

所有權

  • Rust的核心特性就是所有權
  • 所有程序在運行時都必須管理它們使用計算機內存的方式
    • 有些語言有垃圾收集機制,在程序運行時,他們會不斷地尋找不再使用的內存
    • 在其他語言中,程序員必須顯示地分配和釋放內存
  • Rust采用了第三種方式
    • 內存是通過一個所有權系統來管理的,其中包含一組編譯器在編譯時檢查的規則
    • 當程序運行時,所有權特性不會減慢程序的運行速度

棧內存(Stack)/堆內存(Heap)

  • 棧內存
    • 后進先出
    • 所有存儲在棧內存上的數據必須擁有已知的固定大小
      • 編譯時大小未知的數據或運行時大小可能發送改變的數據必須放在堆內存上
  • 堆內存
    • 內存組織性差一些
      • 當把數據放入堆內存時,會請求一定數量的空間
      • 操作系統在堆內存里找到一塊足夠大空間,把他標記為在用,并返回一個指針,也就是這個空間的地址
      • 這個過程叫做在堆內存上進行內存分配,有時僅稱為 分配
  • 把值壓到棧內存上不叫分配
  • 因為指針是已知固定大小的,可以把指針存放在棧內存上
    • 但如果想要實際數據,必須使用指針來定位
  • 把數據壓到棧內存上要比在堆內存上分配快得多
    • 因為操作系統不需要尋找用來存儲新數據的空間,那個位置永遠都在棧內存的頂端
    • 在堆內存上分配空間需要做更多的工作
      • 操作系統需要找到一個足夠大的空間來存放數據,然后要做好記錄方便下次分配
  • 訪問堆內存中的數據要比訪問棧內存中的數據慢,因為需要通過指針才能找到堆內存中的數據
    • 對于現代的處理器來說,由于緩存的緣故,如果指令在內存中跳轉的次數越少,那么速度就越快

函數調用

  • 調用函數時,值被傳入到函數(也包括指向堆內存的指針)。函數本地的變量被壓到棧內存上。當函數結束后,這些值會從棧內存上彈出。

所有權存在的原因

  • 所有權解決的問題

    • 跟蹤代碼的哪些部分正在使用堆內存的哪些數據
    • 最小化堆內存上的重復數據量
    • 清理堆內存上未使用的數據以避免空間不足
  • 所有權規則

    • 每個值都有一個變量,這個變量是該值的所有者
    • 每個值同時只能有一個所有者
    • 當所有者超出作用域(scope)時,該值將被刪除

返回值與作用域

  • 函數在返回值的過程中同樣也會發生所有權的轉移
  • 一個變量的所有權總是遵循同樣的模式:
    • 把一個值賦值給其他變量時就發生移動
    • 當一個包含堆內存數據的變量離開作用域時,它的值就會被drop函數清理,除非數據的所有權移動到另一個變量上了

引用

  • &表示引用,允許你引用某些值而不取得其所有權

借用

  • 把引用作為函數參數這個行為叫做借用
  • 不可以修改借用的東西
  • 和變量一樣,引用默認也是不可變的

可變引用

#![allow(warnings)]
use std::io;
use std::error::Error;
use std::boxed::Box;
use std::convert::TryInto;
use std::cmp::Ordering;
use std::cmp::min;
use std::cmp::max;fn calculate_length(s: &mut String) -> usize {s.push_str(" LTPP");s.len()
}fn main() -> Result<(), Box<dyn Error>> {let mut s1: String = String::from("SQS");println!("{} {}", s1, s1.len());let len: usize = calculate_length(&mut s1);println!("{} {}", s1, len);Ok(())
}

運行結果

SQS 3
SQS LTPP 8
  • 在特定作用域內,對于某一塊數據,只能有一個可變的引用

    • 好處:在編譯時解決數據競爭
  • 以下三種行為會發生數據競爭

    • 兩個或多個指針同時訪問一個數據
    • 至少有一個指針用于寫數據
    • 沒有使用任何機制來同步數據的訪問
  • 可以通過創建新的作用域,來允許非同時的創建多個可變引用

#![allow(warnings)]
use std::io;
use std::error::Error;
use std::boxed::Box;
use std::convert::TryInto;
use std::cmp::Ordering;
use std::cmp::min;
use std::cmp::max;fn main() -> Result<(), Box<dyn Error>> {let mut s1: String = String::from("SQS");{let s2: String = String::from("LTPP");// s2 離開當前作用域后被銷毀}let s1_2 = &mut s1; // s1_2為SQSprintln!("{}", s1_2);let s2_2 = &mut s2; // 報錯,s2在當前作用域不存在println!("{}", s1_2); Ok(())
}

運行結果

編譯出錯!
error[E0425]: cannot find value `s2` in this scope--> /main.rs:19:21|
19 |     let s2_2 = &mut s2; // 報錯,s2在當前作用域不存在|                     ^^ help: a local variable with a similar name exists: `s1`error: aborting due to previous errorFor more information about this error, try `rustc --explain E0425`.
  • 不可同時擁有一個可變引用和一個不可變引用
  • 多個不可變的引用是可以的
#![allow(warnings)]
use std::io;
use std::error::Error;
use std::boxed::Box;
use std::convert::TryInto;
use std::cmp::Ordering;
use std::cmp::min;
use std::cmp::max;fn main() -> Result<(), Box<dyn Error>> {let mut s: String = String::from("SQS");let r1 = &s;let r2 = &s;let s1 = &mut s;println!("{} {} {}", r1, r2, s1);Ok(())
}

運行結果

編譯出錯!
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable--> /main.rs:14:14|
12 |     let r1 = &s;|              -- immutable borrow occurs here
13 |     let r2 = &s;
14 |     let s1 = &mut s;|              ^^^^^^ mutable borrow occurs here
15 |     println!("{} {} {}", r1, r2, s1);|                          -- immutable borrow later used hereerror: aborting due to previous errorFor more information about this error, try `rustc --explain E0502`.

懸空引用

  • 懸空指針:一個指針引用了內存中的某個地址,而這塊內存可能已經釋放并分配給其他人使用了
#![allow(warnings)]
use std::io;
use std::error::Error;
use std::boxed::Box;
use std::convert::TryInto;
use std::cmp::Ordering;
use std::cmp::min;
use std::cmp::max;fn dangle() -> &String {let s: String = String::from("SQS");&s
}fn main() -> Result<(), Box<dyn Error>> {let r = dangle();Ok(())
}

運行結果ust

編譯出錯!
error[E0106]: missing lifetime specifier--> /main.rs:10:16|
10 | fn dangle() -> &String {|                ^ expected named lifetime parameter|= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime|
10 | fn dangle() -> &'static String {|                 +++++++error: aborting due to previous errorFor more information about this error, try `rustc --explain E0106`.
  • Rust里,編譯器可保證引用永遠都不是懸空引用

    • 如果引用了某些數據,編譯器保證在引用離開作用域之前數據不會離開作用域
  • 引用的規則,任意給定的時刻,只能滿足以下情況之一

    • 一個可變的引用
    • 任意數量不可變的引用

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20603.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20603.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20603.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spark大數據 掌握RDD的創建

在Apache Spark中&#xff0c;彈性分布式數據集&#xff08;Resilient Distributed Dataset&#xff0c;簡稱RDD&#xff09;是一個核心的數據結構&#xff0c;用于表示不可變、可分區、可并行操作的元素集合。理解并掌握RDD的創建是使用Spark進行大數據處理的關鍵步驟之一。 …

Qt Creator(Qt 6.6)拷貝一行

Edit - Preference - Environment&#xff1a; 可看到&#xff0c;拷貝一行的快捷鍵是&#xff1a; ctrl Ins

數據結構-堆(帶圖)詳解

前言 本篇博客我們來仔細說一下二叉樹順序存儲的堆的結構&#xff0c;我們來看看堆到底如何實現&#xff0c;以及所謂的堆排序到底是什么 &#x1f493; 個人主頁&#xff1a;普通young man-CSDN博客 ? 文章專欄&#xff1a;數據結構_普通young man的博客-CSDN博客 若有問題 評…

程序員是牛馬嗎?

在今天的討論中&#xff0c;一個引人深思的問題被提出&#xff1a;程序員是否只是現代社會的牛馬&#xff1f;這個問題迅速引發了激烈的爭論。許多程序員開始意識到&#xff0c;盡管他們辛勤工作&#xff0c;但最終可能仍無法擺脫被剝削的命運。因此&#xff0c;他們渴望改變&a…

MySQL(二)-基礎操作

一、約束 有時候&#xff0c;數據庫中數據是有約束的&#xff0c;比如 性別列&#xff0c;你不能填一些奇奇怪怪的數據~ 如果靠人為的來對數據進行檢索約束的話&#xff0c;肯定是不行的&#xff0c;人肯定會犯錯~因此就需要讓計算機對插入的數據進行約束要求&#xff01; 約…

混合模型方差分析

文章目錄 一、說明二、受試者“間”因素和受試者“內”因素的意思&#xff1f;三、混合模型方差分析回答 3 件事四、混合模型方差分析的假設 一、說明 在本文中&#xff0c;我將討論一種稱為混合模型方差分析的方差分析變體&#xff0c;也稱為具有重復測量的 2 因素方差分析。…

音視頻開發_SDL事件處理

今天我為大家介紹一下SDL的事件處理。這里所指的事件處理就是我們通常所說的&#xff0c;鍵盤事件&#xff0c;鼠標事件&#xff0c;窗口事件等。 SDL對這些事件都做了封裝&#xff0c;提供了統一的API&#xff0c;下面我們就來詳細的看一下。 SDL中的事件處理 要想了解 SDL…

VB.net進行CAD二次開發(四)

netload不能彈出對話框&#xff0c;參考文獻2 參考文獻1說明了自定義菜單的問題&#xff0c;用的是cad的系統命令 只要加載了dll&#xff0c;自定義的命令與cad的命令同等地位。 這時&#xff0c;可以將自定義菜單的系統命令替換為自定義命令。 <CommandMethod("Add…

STL-queue的使用及其模擬實現

在C標準庫中&#xff0c;隊列(queue)是一種容器適配器&#xff0c;它以先進先出的方式組織數據&#xff0c;其中從容器一端插入元素&#xff0c;另一端取出元素。 queue的使用 queue的構造函數 queue的成員函數 empty&#xff1a;檢測隊列是否為空size&#xff1a;返回隊列中有…

代碼隨想錄算法訓練營 day23| ● 669. 修剪二叉搜索樹 ● 108.將有序數組轉換為二叉搜索樹 ● 538.把二叉搜索樹轉換為累加樹

文章目錄 前言669. 修剪二叉搜索樹思路方法一 遞歸法方法二 迭代法 108.將有序數組轉換為二叉搜索樹思路方法一 遞歸法方法二 迭代法 538.把二叉搜索樹轉換為累加樹思路方法一方法二 總結 前言 迭代法都沒看主要是669和538【538很簡單】 669. 修剪二叉搜索樹 思路 不用看教程…

【C++刷題】優選算法——位運算

常見位運算操作總結&#xff1a; 基礎位運算 &&#xff1a;有0則為0 |&#xff1a;有1則為1 ^&#xff1a;相同為0&#xff0c;相異為1 / 無進位相加運算符的優先級 管它什么優先級&#xff0c;加括號就完事兒了給一個數 n&#xff0c;確定它的二進制表示中的第 i (默認是從…

【基本數據結構】平衡二叉樹

文章目錄 前言平衡二叉樹1 簡介2 旋轉2.1 左旋2.2 右旋2.3 何時旋轉 3 插入節點4 刪除節點5 代碼 參考資料寫在最后 前言 本系列專注更新基本數據結構&#xff0c;現有以下文章&#xff1a; 【算法與數據結構】數組. 【算法與數據結構】鏈表. 【算法與數據結構】哈希表. 【…

【斯坦福因果推斷課程全集】1_隨機對照試驗1

目錄 The average treatment effect Difference-in-means estimation IID Sampling and Population Asymptotics Example: The linear model Regression adjustments with a linear model 隨機對照試驗&#xff08;RCT&#xff09;是統計因果推論的基礎。如果有的話&#…

關于FPGA 使用SPI FLASH固化時如何配置固化參數

關于FPGA 使用SPI FLASH固化時如何配置固化參數 EDA工具&#xff1a;Vivado 關于FPGA 使用SPI FLASH固化時如何配置固化參數一、引言二、如何設置固化參數&#xff1a;使用50M的速度 &#xff0c;SPI為X4 &#xff0c;以及bit壓縮第一&#xff1a;點open implenment design第二…

Android之onMeasure的三種模式

Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}在 Android 中&#xff0c;onMeasure() 方法是 View 或 ViewGroup 中的一個重要方法&#xff0c;用于測量視圖的大小。在 onMeasure(…

安裝軟件缺少dll文件怎么辦,分享多種解決dll問題的方法

在計算機使用過程中&#xff0c;我們經常會遇到安裝軟件時提示缺少dll文件的問題。這種情況通常會導致軟件無法正常運行或啟動。為了解決這個問題&#xff0c;我總結了以下五種方法&#xff0c;希望對大家有所幫助。 一&#xff0c;了解DLL文件是什么 動態鏈接庫&#xff08;D…

簡單說說我對集成學習算法的一點理解

概要 集成學習&#xff08;Ensemble Learning&#xff09;是一種機器學習技術框架&#xff0c;它通過構建并結合多個學習器&#xff08;也稱為個體學習器或基學習器&#xff09;來完成學習任務。 集成學習旨在通過組合多個基學習器的預測結果來提高整體模型的性能。每個基學習…

常見儀表盤指示燈的含義,這次夠全了!

汽車是當前主要的交通工具之一&#xff0c;給人們的工作、生活提供了便利。大家在學會開車的同時&#xff0c;也得了解一些基本的汽車常識&#xff0c;可以及時的發現車輛的問題&#xff0c;并作出正確的判斷&#xff0c;以此降低車輛的損耗和維修成本。其中最基本的&#xff0…

房產證上加名?手把手教你操作,省錢又省心!

隨著《民法典》的實施&#xff0c;房產的權屬問題愈發受到重視。夫妻雙方及其親屬常希望能在房產證上增添自己的名字&#xff0c;以保障各自的權益。那么&#xff0c;房產證上到底能寫幾個名字呢&#xff1f;以下是對這一問題的詳細解答。 一、房產證命名無固定限制 在購房時&…

準確-K8s系列文章-修改containerd 默認數據目錄

修改 Kubernetes 集群中 containerd 默認數據目錄為 /data/containerd 前言 本文檔適用于 Kubernetes 1.24 及以上版本的集群,介紹如何將 containerd 默認的數據目錄從 /var/lib/containerd 修改為 /data/containerd。 步驟 1. 停止 containerd 服務(慎重!!!需評估風險!…