最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你掌握Rust中的字符串與切片

 更新時(shí)間:2026年03月30日 09:47:12   作者:Rust研習(xí)社  
字符串與切片是所有新手遇到的第一個(gè)門(mén)檻,不同于?Java、Python?等語(yǔ)言對(duì)字符串的高度封裝,Rust?的字符串與切片深度綁定了所有權(quán)、借用、生命周期與?UTF-8?編碼,下面小編就和大家詳細(xì)介紹一下吧

字符串與切片是所有新手遇到的第一個(gè)門(mén)檻,不同于 Java、Python 等語(yǔ)言對(duì)字符串的高度封裝,Rust 的字符串與切片深度綁定了所有權(quán)、借用、生命周期與 UTF-8 編碼,從編譯期就將亂碼、內(nèi)存安全等問(wèn)題解決。

什么是切片(Slice)

字符串是切片的特殊場(chǎng)景,想要理解字符串,必須先搞懂切片。在 Rust 里,切片是描述一組屬于同一類型、長(zhǎng)度不確定的、在內(nèi)存中連續(xù)存放的數(shù)據(jù)結(jié)構(gòu),用 [T] 來(lái)表述。因?yàn)殚L(zhǎng)度不確定,切片屬于動(dòng)態(tài)大小類型(DST, Dynamically Sized Type),無(wú)法直接在棧上存儲(chǔ),必須通過(guò)引用(&[T],不可變切片)或可變引用(&mut [T],可變切片)來(lái)使用。

切片通過(guò) Rust 的范圍語(yǔ)法 [start..end] 創(chuàng)建,遵循左閉右開(kāi)原則,支持多種簡(jiǎn)寫(xiě)形式:

  • [a..b]:從索引 ab-1 的切片
  • [a..]:從索引 a 到集合末尾的切片
  • [..b]:從集合開(kāi)頭到索引 b-1 的切片
  • [..]:覆蓋整個(gè)集合的全切片

示例如下:

fn main() {
    // 原數(shù)組:切片的底層數(shù)據(jù)所有者
    let arr = [1, 2, 3, 4, 5];
    
    // 創(chuàng)建切片:引用數(shù)組的第1到第3個(gè)元素
    let slice: &[i32] = &arr[1..4];
    println!("切片內(nèi)容: {:?}", slice); // 輸出 [2, 3, 4]
    println!("切片長(zhǎng)度: {}", slice.len()); // 輸出 3
    println!("切片是否為空: {}", slice.is_empty()); // 輸出 false
}

Rust 的切片從編譯期就杜絕了兩類經(jīng)典內(nèi)存問(wèn)題:

  1. 越界訪問(wèn):編譯期會(huì)校驗(yàn)切片范圍,運(yùn)行時(shí)也會(huì)做邊界檢查,直接拒絕非法訪問(wèn)
  2. 懸垂引用:生命周期規(guī)則保證,只要切片有效,底層數(shù)據(jù)的所有者就一定不會(huì)被釋放或修改

示例如下:

// 獲取數(shù)組中第一個(gè)非零元素的切片
fn first_non_zero(arr: &[i32]) -> &[i32] {
    for (i, &num) in arr.iter().enumerate() {
        if num != 0 {
            return &arr[i..];
        }
    }
    &arr[..0]
}

fn main() {
    let arr = [0, 0, 3, 5, 7];
    let non_zero_slice = first_non_zero(&arr);
    
    // 編譯報(bào)錯(cuò):無(wú)法修改原數(shù)組,因?yàn)樗呀?jīng)被切片借用
    // arr[2] = 0;
    
    println!("非零切片: {:?}", non_zero_slice); // 輸出 [3, 5, 7]
}

這個(gè)例子體現(xiàn)了 Rust 的安全哲學(xué):在切片的生命周期內(nèi),原數(shù)據(jù)無(wú)法被修改,徹底避免了數(shù)據(jù)競(jìng)爭(zhēng)與懸垂引用。

Rust 字符串的兩大核心類型

Rust 的字符串體系看似復(fù)雜,核心只有兩個(gè)類型,其他都是面向特定場(chǎng)景的擴(kuò)展:

  • &str:字符串切片,無(wú)所有權(quán),只讀,是切片的 UTF-8 版本
  • String:可擁有、可修改的字符串類型,底層是堆上分配的 Vec<u8> 封裝

兩者的關(guān)系如同 &[T]Vec<T>&str 是數(shù)據(jù)的“視圖”,String 是數(shù)據(jù)的“所有者”。

Rust 字符串的核心設(shè)計(jì):強(qiáng)制 UTF-8 編碼

很多新手可能會(huì)困惑為什么 Python、Go 可以直接用索引 s[i] 取字符,而 Rust 卻不行?原因在于:Rust 的字符串強(qiáng)制使用 UTF-8 編碼,而 UTF-8 是變長(zhǎng)編碼。

  • ASCII 字符占 1 個(gè)字節(jié)
  • 中文、日文等東亞字符占 3 個(gè)字節(jié)
  • Emoji 等特殊字符占 4 個(gè)字節(jié)

如果允許直接按索引訪問(wèn),會(huì)帶來(lái)兩個(gè)致命問(wèn)題:

  • 索引訪問(wèn)的時(shí)間復(fù)雜度不再是 O(1),必須遍歷字符串才能定位到對(duì)應(yīng)字符
  • 極易訪問(wèn)到字符的中間字節(jié),生成非法 UTF-8 序列,引發(fā)未定義行為(UB)

因此 Rust 從語(yǔ)法層面禁止了直接通過(guò)索引訪問(wèn)字符串字符,只允許通過(guò)合法的方式遍歷和操作。

字節(jié)與字符的正確操作

fn main() {
    let s = "你好Rust";
    println!("字節(jié)長(zhǎng)度: {}", s.len()); // 輸出 10(2個(gè)中文*3字節(jié) + 4個(gè)ASCII字符=10)
    println!("字符數(shù)量: {}", s.chars().count()); // 輸出 6
    
    // 正確方式1:遍歷所有字符(Unicode標(biāo)量值)
    println!("=== 字符遍歷 ===");
    for c in s.chars() {
        println!("字符: {}", c);
    }
    
    // 正確方式2:遍歷所有字節(jié)
    println!("=== 字節(jié)遍歷 ===");
    for b in s.bytes() {
        println!("字節(jié): {}", b);
    }
}

字符串切片的致命坑:字符邊界問(wèn)題

Rust 編譯期不會(huì)檢查切片范圍是否符合 UTF-8 字符邊界,只有運(yùn)行時(shí)會(huì)校驗(yàn),一旦切到字符中間,會(huì)直接觸發(fā) panic。

fn main() {
    let s = "你好";
    // 反例:運(yùn)行時(shí) panic!"你"占3個(gè)字節(jié),[0..2]切到了字符中間
    // let sub = &s[0..2];
    
    // 正確示例:嚴(yán)格按字符邊界切片
    let sub = &s[0..3];
    println!("{}", sub); // 輸出 你
}

所以在實(shí)際開(kāi)發(fā)中最佳實(shí)踐是:不要硬編碼索引切片字符串,優(yōu)先通過(guò) chars().enumerate() 定位字符位置,再進(jìn)行切片操作。

字符串與切片的實(shí)戰(zhàn)常用操作

String 的修改操作(僅所有者可用)

只有持有所有權(quán)的 String 可以修改內(nèi)容,常用方法如下:

fn main() {
    let mut s = String::from("Hello");

    // 追加字符串切片
    s.push_str(" World");
    // 追加單個(gè)字符
    s.push('!');
    println!("{}", s); // 輸出 Hello World!

    // 插入字符
    s.insert(5, ',');
    println!("{}", s); // 輸出 Hello, World!

    // 彈出最后一個(gè)字符
    let last_char = s.pop();
    println!("彈出的字符: {:?}", last_char); // 輸出 Some('!')

    // 清空字符串
    s.clear();
    println!("清空后是否為空: {}", s.is_empty()); // 輸出 true
}

字符串拼接的三種方式與選型

方法用法所有權(quán)影響適用場(chǎng)景
+ 運(yùn)算符String + &str左側(cè) String 所有權(quán)被轉(zhuǎn)移簡(jiǎn)單拼接,無(wú)需保留原 String
format! 宏format!("{} {}", a, b)不轉(zhuǎn)移任何所有權(quán)復(fù)雜拼接、多變量拼接,可讀性優(yōu)先
push_str 方法s.push_str(&str)僅修改原 String,不轉(zhuǎn)移循環(huán)追加、動(dòng)態(tài)構(gòu)建字符串

示例如下:

fn main() {
    let s1 = String::from("Hello");
    let s2 = "Rust";

    // + 運(yùn)算符:s1所有權(quán)被轉(zhuǎn)移,后續(xù)無(wú)法使用
    let s3 = s1 + " " + s2;
    println!("+ 拼接結(jié)果: {}", s3); // 輸出 Hello Rust

    // format! 宏:不轉(zhuǎn)移所有權(quán),最靈活
    let a = String::from("你好");
    let b = String::from("世界");
    let c = format!("{},{}!", a, b);
    println!("format! 結(jié)果: {}", c); // 輸出 你好,世界!
    println!("a仍可用: {}", a); // 所有權(quán)未轉(zhuǎn)移,可正常使用
}

字符串切片的常用工具方法

fn main() {
    let s = "  Hello Rust  ";

    // 去除首尾空白
    println!("trim后: '{}'", s.trim()); // 輸出 'Hello Rust'

    // 前綴/后綴判斷
    let trimmed = s.trim();
    println!("是否以Hello開(kāi)頭: {}", trimmed.starts_with("Hello")); // 輸出 true
    println!("是否以Rust結(jié)尾: {}", trimmed.ends_with("Rust")); // 輸出 true

    // 包含判斷與查找
    println!("是否包含Rust: {}", s.contains("Rust")); // 輸出 true
    println!("Rust的起始位置: {:?}", s.find("Rust")); // 輸出 Some(8)

    // 分割字符串
    let parts: Vec<&str> = trimmed.split_whitespace().collect();
    println!("分割結(jié)果: {:?}", parts); // 輸出 ["Hello", "Rust"]
}

最常用的轉(zhuǎn)換:String 與 & str 的互轉(zhuǎn)

Rust 提供了非常便捷的轉(zhuǎn)換能力,核心是 Deref 強(qiáng)制轉(zhuǎn)換機(jī)制:&String 可以自動(dòng)被編譯器轉(zhuǎn)換為 &str,無(wú)需手動(dòng)處理。

這也是實(shí)際開(kāi)發(fā)中的一個(gè)最佳實(shí)踐:函數(shù)參數(shù)優(yōu)先使用 &str,而非 &String。因?yàn)?&str 可以同時(shí)接受字符串字面量、&String、其他字符串切片,通用性最大。

// 函數(shù)參數(shù)使用&str,獲得最大通用性
fn print_info(s: &str) {
    println!("內(nèi)容: {},字節(jié)長(zhǎng)度: {}", s, s.len());
}

fn main() {
    let s = String::from("Hello Rust");
    
    // 直接傳&String,自動(dòng)轉(zhuǎn)換為&str
    print_info(&s);
    
    // 傳字符串字面量,完全兼容
    print_info("你好世界");
    
    // 手動(dòng)創(chuàng)建全切片,效果完全一致
    print_info(&s[..]);
}

擴(kuò)展:其他字符串相關(guān)類型

除了核心的 &strString,Rust 標(biāo)準(zhǔn)庫(kù)還提供了面向特定場(chǎng)景的字符串類型,無(wú)需深入學(xué)習(xí),了解其用途即可:

  • OsStr/OsString:操作系統(tǒng)兼容的字符串,支持非 UTF-8 的路徑、系統(tǒng)參數(shù),位于 std::ffi 模塊
  • CStr/CString:與 C 語(yǔ)言交互的字符串,以 \0 結(jié)尾,符合 C 語(yǔ)言字符串規(guī)范,位于 std::ffi 模塊
  • Path/PathBuf:路徑專用類型,基于 OsStr 封裝,提供路徑相關(guān)的專用方法,位于 std::path 模塊

總結(jié)

Rust 的字符串與切片設(shè)計(jì),看似嚴(yán)苛,實(shí)則是圍繞內(nèi)存安全、UTF-8 原生支持和零成本抽象三個(gè)核心目標(biāo),它把其他語(yǔ)言中運(yùn)行時(shí)才會(huì)暴露的字符串亂碼、越界、懸垂引用等問(wèn)題,提前到了編譯期解決。

理解這些設(shè)計(jì)背后的邏輯,你就能真正掌握 Rust 字符串與切片,寫(xiě)出既安全又高效的代碼。

以上就是一文帶你掌握Rust中的字符串與切片的詳細(xì)內(nèi)容,更多關(guān)于Rust字符串與切片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Rust調(diào)用Windows API 如何獲取正在運(yùn)行的全部進(jìn)程信息

    Rust調(diào)用Windows API 如何獲取正在運(yùn)行的全部進(jìn)程信息

    本文介紹了如何使用Rust調(diào)用WindowsAPI獲取正在運(yùn)行的全部進(jìn)程信息,通過(guò)引入winapi依賴并添加相應(yīng)的features,可以實(shí)現(xiàn)對(duì)不同API集的調(diào)用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • rust 中的 EBNF簡(jiǎn)介舉例

    rust 中的 EBNF簡(jiǎn)介舉例

    這篇文章主要介紹了rust 中的 EBNF簡(jiǎn)介舉例,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-05-05
  • Rust?Atomics?and?Locks?源碼解讀

    Rust?Atomics?and?Locks?源碼解讀

    這篇文章主要為大家介紹了Rust?Atomics?and?Locks?源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • rust 一個(gè)日志緩存記錄的通用實(shí)現(xiàn)方法

    rust 一個(gè)日志緩存記錄的通用實(shí)現(xiàn)方法

    本文給出了一個(gè)通用的設(shè)計(jì)模式,通過(guò)建造者模式實(shí)例化記錄對(duì)象,可自定義格式化器將實(shí)例化后的記錄對(duì)象寫(xiě)入到指定的緩存對(duì)象中,這篇文章主要介紹了rust 一個(gè)日志緩存記錄的通用實(shí)現(xiàn)方法,需要的朋友可以參考下
    2024-04-04
  • Rust-使用dotenvy加載和使用環(huán)境變量的過(guò)程詳解

    Rust-使用dotenvy加載和使用環(huán)境變量的過(guò)程詳解

    系統(tǒng)的開(kāi)發(fā),測(cè)試和部署離不開(kāi)環(huán)境變量,今天分享在Rust的系統(tǒng)開(kāi)發(fā)中,使用dotenvy來(lái)讀取和使用環(huán)境變量,感興趣的朋友跟隨小編一起看看吧
    2023-11-11
  • Rust?duckdb和polars讀csv文件比較情況

    Rust?duckdb和polars讀csv文件比較情況

    duckdb在數(shù)據(jù)分析上,有非常多不錯(cuò)的特質(zhì),1、快;2、客戶體驗(yàn)好,特別是可以同時(shí)批量讀csv在一個(gè)目錄下的csv等文件,今天來(lái)比較下Rust?duckdb和polars讀csv文件比較的情況,感興趣的朋友一起看看吧
    2024-06-06
  • 使用環(huán)境變量實(shí)現(xiàn)Rust程序中的不區(qū)分大小寫(xiě)搜索方式

    使用環(huán)境變量實(shí)現(xiàn)Rust程序中的不區(qū)分大小寫(xiě)搜索方式

    本文介紹了如何在Rust中實(shí)現(xiàn)不區(qū)分大小寫(xiě)的搜索功能,并通過(guò)測(cè)試驅(qū)動(dòng)開(kāi)發(fā)(TDD)方法逐步實(shí)現(xiàn)該功能,通過(guò)修改運(yùn)行函數(shù)和獲取環(huán)境變量,程序可以根據(jù)環(huán)境變量控制搜索模式
    2025-02-02
  • 教你使用RustDesk?搭建一個(gè)自己的遠(yuǎn)程桌面中繼服務(wù)器

    教你使用RustDesk?搭建一個(gè)自己的遠(yuǎn)程桌面中繼服務(wù)器

    這篇文章主要介紹了RustDesk?搭建一個(gè)自己的遠(yuǎn)程桌面中繼服務(wù)器,主要包括服務(wù)端安裝和客戶端配置方法,配置好相關(guān)操作輸入控制碼即可發(fā)起遠(yuǎn)程或文件傳輸,本文通過(guò)圖文給大家講解的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • rust將bitmap位圖文件另存為png格式的方法

    rust將bitmap位圖文件另存為png格式的方法

    通過(guò)添加依賴,轉(zhuǎn)換函數(shù)和單元測(cè)試操作步驟來(lái)解決將bitmap位圖文件另存為png格式文件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)rust bitmap位另存為png格式的操作方法感興趣的朋友一起看看吧
    2024-03-03
  • Rust+React創(chuàng)建富文本編輯器

    Rust+React創(chuàng)建富文本編輯器

    這篇文章主要為大家介紹了Rust+React創(chuàng)建富文本編輯器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評(píng)論

大竹县| 台湾省| 庆城县| 阿拉尔市| 泽普县| 鸡泽县| 兴隆县| 南康市| 古丈县| 安宁市| 镇远县| 金塔县| 蕉岭县| 兴城市| 华阴市| 舟山市| 高平市| 临夏县| 张家港市| 涞水县| 定结县| 婺源县| 乃东县| 汾西县| 康平县| 昌乐县| 晋宁县| 沐川县| 马尔康县| 德钦县| 内丘县| 安泽县| 体育| 兴和县| 乡宁县| 综艺| 伽师县| 白河县| 福建省| 安新县| 松潘县|