本文简要介绍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。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。