當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Rust String用法及代碼示例


本文簡要介紹rust語言中 Struct std::string::String 的用法。

用法

pub struct String { /* fields omitted */ }

一個 UTF-8 編碼的、可增長的字符串。

String 類型是最常見的字符串類型,它擁有對字符串內容的所有權。它與其借用的對應物原語 str 有著密切的關係。

例子

您可以使用 String::from a literal string 創建 String

let hello = String::from("Hello, world!");

您可以使用 push 方法將 char 附加到String,並使用 push_str 方法附加 &str

let mut hello = String::from("Hello, ");

hello.push('w');
hello.push_str("orld!");

如果你有一個 UTF-8 字節的向量,你可以使用 from_utf8 方法從它創建一個 String

// some bytes, in a vector
let sparkle_heart = vec![240, 159, 146, 150];

// We know these bytes are valid, so we'll use `unwrap()`.
let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();

assert_eq!("💖", sparkle_heart);

UTF-8

String 始終是有效的 UTF-8。這有一些含義,首先是如果您需要非 UTF-8 字符串,請考慮 OsString 。它類似,但沒有 UTF-8 約束。第二個含義是您不能索引到 String

let s = "hello";

println!("The first letter of s is {}", s[0]); // ERROR!!!

索引旨在成為 constant-time 操作,但 UTF-8 編碼不允許我們這樣做。此外,還不清楚索引應該返回什麽樣的東西:一個字節、一個代碼點或一個字形簇。 bytes chars 方法分別返回前兩個的迭代器。

去參考

String 實現了 Deref<Target = str> ,因此繼承了所有 str 的方法。此外,這意味著您可以通過使用與號 (&) 將 String 傳遞給采用 &str 的函數:

fn takes_str(s: &str) { }

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

takes_str(&s);

這將從 String 創建一個 &str 並將其傳入。這種轉換非常便宜,因此通常,函數將接受 &str 作為參數,除非它們出於某種特定原因需要 String

在某些情況下,Rust 沒有足夠的信息來進行這種轉換,稱為 Deref coercion。在下麵的示例中,字符串切片 &'a str 實現了特征 TraitExample ,函數 example_func 采用任何實現特征的東西。在這種情況下,Rust 需要進行兩次隱式轉換,而 Rust 沒有辦法做到這一點。因此,以下示例將無法編譯。

trait TraitExample {}

impl<'a> TraitExample for &'a str {}

fn example_func<A: TraitExample>(example_arg: A) {}

let example_string = String::from("example_string");
example_func(&example_string);

有兩個選項可以代替。第一個是將行 example_func(&example_string); 更改為 example_func(example_string.as_str()); ,使用方法 as_str() 顯式提取包含字符串的字符串切片。第二種方式將 example_func(&example_string); 更改為 example_func(&*example_string); 。在這種情況下,我們將 String 取消引用到 str ,然後將 str 引用回 &str 。第二種方式更慣用,但是兩者都可以顯式地進行轉換,而不是依賴於隱式轉換。

表示

String 由三個部分組成:指向某些字節的指針、長度和容量。指針指向一個內部緩衝區 String 用於存儲其數據。長度是當前存儲在緩衝區中的字節數,容量是緩衝區的大小(以字節為單位)。因此,長度將始終小於或等於容量。

此緩衝區始終存儲在堆上。

您可以使用 as_ptr len capacity 方法查看這些:

use std::mem;

let story = String::from("Once upon a time...");

// Prevent automatically dropping the String's data
let mut story = mem::ManuallyDrop::new(story);

let ptr = story.as_mut_ptr();
let len = story.len();
let capacity = story.capacity();

// story has nineteen bytes
assert_eq!(19, len);

// We can re-build a String out of ptr, len, and capacity. This is all
// unsafe because we are responsible for making sure the components are
// valid:
let s = unsafe { String::from_raw_parts(ptr, len, capacity) } ;

assert_eq!(String::from("Once upon a time..."), s);

如果String 有足夠的容量,向其中添加元素不會重新分配。例如,考慮這個程序:

let mut s = String::new();

println!("{}", s.capacity());

for _ in 0..5 {
    s.push_str("hello");
    println!("{}", s.capacity());
}

這將輸出以下內容:

0
5
10
20
20
40

起初,我們根本沒有分配內存,但是當我們追加到字符串時,它會適當地增加它的容量。如果我們改為使用 with_capacity 方法來分配正確的容量:

let mut s = String::with_capacity(25);

println!("{}", s.capacity());

for _ in 0..5 {
    s.push_str("hello");
    println!("{}", s.capacity());
}

我們最終得到不同的輸出:

25
25
25
25
25
25

在這裏,無需在循環內分配更多內存。

相關用法


注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Struct std::string::String。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。