本文簡要介紹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 String.try_reserve用法及代碼示例
- Rust String.insert_str用法及代碼示例
- Rust String.into_raw_parts用法及代碼示例
- Rust String.extend_from_within用法及代碼示例
- Rust String.clear用法及代碼示例
- Rust String.reserve用法及代碼示例
- Rust String.from_utf16_lossy用法及代碼示例
- Rust String.push用法及代碼示例
- Rust String.as_bytes用法及代碼示例
- Rust String.as_str用法及代碼示例
- Rust String.with_capacity用法及代碼示例
- Rust String.remove用法及代碼示例
- Rust String.from_utf8_lossy用法及代碼示例
- Rust String.into_bytes用法及代碼示例
- Rust String.replace_range用法及代碼示例
- Rust String.split_off用法及代碼示例
- Rust String.from_utf16用法及代碼示例
- Rust String.shrink_to_fit用法及代碼示例
- Rust String.from_utf8_unchecked用法及代碼示例
- Rust String.into_boxed_str用法及代碼示例
- Rust String.new用法及代碼示例
- Rust String.insert用法及代碼示例
- Rust String.capacity用法及代碼示例
- Rust String.try_reserve_exact用法及代碼示例
- Rust String.as_mut_str用法及代碼示例
注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Struct std::string::String。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。