在rust开发过程中我们常常会遇到
String,&str和str三个概念,总是朦胧不清,分不清三者之间的关系以及区别,实际开发过程中总是因为分不清三者之间的用法而郁闷苦恼,今天我带你们就详细的探索三者之间的关系,让你不在朦胧不清,而让你豁然开朗。
-
str:
str是一个字符串字面量,它是一个指向有效UTF-8编码的不可变字符串切片的指针。str类型是一个切片类型,它不拥有数据,而是指向数据。- 它是
&str的别名,通常在模式匹配和函数签名中使用。 - 用法示例:
let s: &str = "Hello, world!";
-
&str:
&str是一个字符串切片,它是一个对字符串数据的不可变引用。- 它允许你借用字符串数据而不需要拥有所有权,因此可以用于借用字符串字面量或者
String类型的数据。 - 用法示例:
let s = String::from("Hello, world!"); let slice: &str = &s;
-
String:
String是一个可增长的、可变的字符串类型,它拥有自己的数据。- 它是
Vec<char>的封装,允许你动态地增加或减少字符串的长度。 String是堆分配的,因此它比&str有更多的内存开销,但是提供了更多的灵活性。- 用法示例:
let mut s = String::new(); s.push_str("Hello, world!");
它们之间的关系和用法如下:
-
所有权与借用:
String拥有其数据,而&str则是对数据的引用。- 你可以将
String传递给函数作为&str,这样函数就可以借用String的数据而不需要拥有它。
-
可变性:
String是可变的,你可以改变它的内容。&str是不可变的,你不能改变它指向的数据。
-
内存分配:
String在堆上分配内存,允许动态调整大小。&str可以指向堆上的数据(如String)或者栈上的数据(如字符串字面量)。
-
性能:
- 由于
&str不需要堆分配,所以使用&str通常比String更高效,尤其是在性能敏感的场景中。
- 由于
-
函数参数:
- 当函数只需要读取字符串内容时,通常使用
&str作为参数类型,这样可以避免不必要的数据复制。 - 当函数需要修改字符串内容时,使用
String作为参数类型。
- 当函数只需要读取字符串内容时,通常使用
用法示例
String 的用法
String 是一个可增长的、可变的 UTF-8 字符串类型,它拥有自己的数据。
fn main() {
// 创建一个空的 String
let mut s = String::new();
// 使用 push_str 方法追加字符串
s.push_str("Hello, ");
s.push_str("world!");
// 使用 + 运算符和 format! 宏来拼接字符串
let greeting = format!("{}{}", s, " How are you?");
// 打印结果
println!("{}", greeting);
}
str 和 &str 的用法
str 是一个字符串切片,它是一个指向有效 UTF-8 编码序列的不可变引用。
fn main() {
// 创建一个 String
let s = String::from("hello world");
// 通过 & 获取一个 str 的引用
let slice: &str = &s;
// 直接使用字符串字面量,它自动被借用为 &str 类型
let word: &str = "hello";
// 使用 str 的方法,比如 len()
println!("Length of slice: {}", slice.len());
println!("Length of word: {}", word.len());
}
String 和 &str 互相转换的用法
fn main() {
// 从 &str 创建 String
let s = String::from("hello world");
let s_as_str: &str = &s; // 将 String 借用为 &str
// 从 &str 创建 String
let str_slice: &str = "I am a string slice";
let str_from_slice = String::from(str_slice); // 将 &str 转换为 String
// 打印结果
println!("String from &str: {}", str_from_slice);
}
&str 作为函数参数的用法
fn main() {
let my_string = String::from("Rust is fun");
// 调用函数,传递字符串的引用
print_first_word(&my_string);
// 直接传递字符串字面量
print_first_word("Hello, Rust!");
}
// 函数接受 &str 类型的参数
fn print_first_word(s: &str) {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
print!("{}", std::str::from_utf8(&bytes[0..i]).unwrap());
break;
}
}
}
在这个例子中,print_first_word 函数接受一个 &str 类型的参数,这意味着它可以接收任何实现了 Deref trait 的类型,包括 String 和字符串字面量。这样,函数可以处理不同的字符串类型,而不需要关心它们的所有权。
最后如果您也喜欢rust,还请您一键三连,让我有动力持续的输出优质的关于rust的内容,正是因为有了您的支撑,才让我有动力走过这段孤独的路。