生锈和#x27;s'String'和'str`?
为什么锈有生锈和#x27;s'String'和'str`?,string,rust,String,Rust,为什么锈有String和str?String和str之间有什么区别?什么时候使用String而不是str,反之亦然?其中一个是否已被弃用?,仅用作&str,是一个字符串片段,是对UTF-8字节数组的引用 是以前的~str,一种可扩展的、自有的UTF-8字节数组。String是动态堆字符串类型,如Vec:需要拥有或修改字符串数据时使用它 str是内存中某个位置动态长度的UTF-8字节的不可变1序列。由于大小未知,因此只能在指针后面处理它。这意味着str最常见的形式是&str:对某些UTF-8数据的
String
和str
?String
和str
之间有什么区别?什么时候使用String
而不是str
,反之亦然?其中一个是否已被弃用?,仅用作&str
,是一个字符串片段,是对UTF-8字节数组的引用
是以前的
~str
,一种可扩展的、自有的UTF-8字节数组。String
是动态堆字符串类型,如Vec
:需要拥有或修改字符串数据时使用它
str
是内存中某个位置动态长度的UTF-8字节的不可变1序列。由于大小未知,因此只能在指针后面处理它。这意味着str
最常见的形式是&str
:对某些UTF-8数据的引用,通常称为“字符串片段”或“片段”。只是一些数据的视图,这些数据可以在任何地方,例如
- 在静态存储中:字符串文本
是一个“foo”
。数据被硬编码到可执行文件中,并在程序运行时加载到内存中和静态str
- 在堆内分配
:字符串的数据字符串
- 在堆栈上:例如,下面创建一个堆栈分配的字节数组,然后获取一个:
String
;如果您只需要字符串的视图,请使用&str
这与向量Vec
和切片&[T]
之间的关系相同,并且与一般类型的按值T
和按引用&T
之间的关系相似
1 A
str
为固定长度;您不能将字节写入结尾之外,或留下尾随的无效字节。由于UTF-8是一种可变宽度编码,因此在许多情况下,这有效地迫使所有str
s都是不可变的。一般来说,突变需要比以前写入更多或更少的字节(例如,将a
(1字节)替换为ä
(2+字节)将需要在str中留出更多空间)。有一些特定的方法可以就地修改&mut str
,主要是那些只处理ASCII字符的方法,如
2允许类似于Rc
的内容用于自Rust 1.2以来计数为UTF-8字节的引用序列。RISE 1.21允许创建这些类型。 < P>我有C++背景,我认为在C++中考虑<代码>字符串和<代码>和STR>代码>非常有用:
- 生锈的
字符串
就像std::String
;它拥有内存,并负责管理内存
- 锈迹
&str
类似于char*
(但有点复杂);它将我们指向块的开头,就像您可以获得指向std::string
内容的指针一样
他们两个会消失吗?我不这么认为。它们有两个目的:
String
保留缓冲区,使用起来非常实用&str
是轻量级的,应该用于“查看”字符串。您可以搜索、分割、解析甚至替换块,而无需分配新内存
&str
可以查看字符串的内部,因为它可以指向某个字符串文本。以下代码需要将文本字符串复制到字符串
托管内存中:
let a: String = "hello rust".into();
下面的代码允许您在不复制的情况下使用文本本身(尽管是只读的)
简单地说,String
是存储在堆上的数据类型(就像Vec
),您可以访问该位置
&str
是一种切片类型。这意味着它只是对堆中某个地方已经存在的字符串的引用
&str
在运行时不进行任何分配。因此,出于内存原因,您可以在字符串上使用&str
。但是,请记住,在使用&str
时,您可能需要处理显式生命周期。它们实际上完全不同。首先,一个str
只不过是一个类型级别的东西;它只能在类型级别进行推理,因为它是所谓的动态大小类型(DST)。str
占用的大小在编译时是未知的,取决于运行时信息-它不能存储在变量中,因为编译器需要在编译时知道每个变量的大小。str
在概念上只是一行u8
字节,保证它形成有效的UTF-8。这排有多大?在运行时之前没有人知道,因此它不能存储在变量中
有趣的是,运行时确实存在&str
或任何指向str
的指针,如框
。这就是所谓的“胖指针”;它是一个带有额外信息的指针(在本例中是指它指向的对象的大小),因此它是两倍大。事实上,&str
与字符串非常接近(但与&String
不同)。A&str
是两个单词;一个指针指向str
的第一个字节,另一个数字描述str
的长度
与所说的相反,str
不需要是不变的。如果您可以获得一个&mut str
作为指向str
的独占指针,那么您可以对其进行变异,并且所有变异的安全函数都可以保证UTF-8约束得到支持,因为如果违反了UTF-8约束,那么我们将有未定义的行为,因为库假定此约束为真,并且不检查它
那么什么是字符串
?那是
let a: String = "hello rust".into();
let a: &str = "hello rust";
let string: String = "a string".to_string();
let substring1: &str = &string[1..3];
let substring2: &str = &string[2..4];
#[derive(PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
vec: Vec<u8>,
}
let mut word = "hello world";
word[0] = 's';
word.push('\n');
let mut s = "Per Martin-Löf".to_string();
{
let (first, last) = s.split_at_mut(3);
first.make_ascii_uppercase();
assert_eq!("PER", first);
assert_eq!(" Martin-Löf", last);
}
assert_eq!("PER Martin-Löf", s);
+----+-----+-----+-----+-----+----+----+-----+-----+-----+-----+
| H | e | l | l | o | | W | o | r | l | d |
+----+-----+-----+-----+-----+----+----+-----+-----+-----+-----+
+----+-----+-----+-----+-----+----+----+-----+-----+-----+-----+
| 72 | 101 | 108 | 108 | 111 | 32 | 87 | 111 | 114 | 108 | 100 |
+----+-----+-----+-----+-----+----+----+-----+-----+-----+-----+
fn main(){
let hello = String::("hello");
let any_char = hello[0];//error
}
fn main(){
let hello = String::("hello");
for c in hello.chars() {
println!("{}",c);
}
}
fn main(){
let hello = String::("String are cool");
let any_char = &hello[5..6]; // = let any_char: &str = &hello[5..6];
println!("{:?}",any_char);
}
fn main() {
let s: &str = "hello"; // &str
let s: String = s.to_uppercase(); // String
println!("{}", s) // HELLO
}
fn say_hello(to_whom: &str) { //type coercion
println!("Hey {}!", to_whom)
}
fn main(){
let string_slice: &'static str = "you";
let string: String = string_slice.into(); // &str => String
say_hello(string_slice);
say_hello(&string);// &String
}
// String is at heap, and can be increase or decrease in its size
// The size of &str is fixed.
fn main(){
let a = "Foo";
let b = "Bar";
let c = a + b; //error
// let c = a.to_string + b;
}
use std::mem;
fn main() {
// on 64 bit architecture:
println!("{}", mem::size_of::<&str>()); // 16
println!("{}", mem::size_of::<String>()); // 24
let string1: &'static str = "abc";
// string will point to `static memory which lives through the whole program
let ptr = string1.as_ptr();
let len = string1.len();
println!("{}, {}", unsafe { *ptr as char }, len); // a, 3
// len is 3 characters long so 3
// pointer to the first character points to letter a
{
let mut string2: String = "def".to_string();
let ptr = string2.as_ptr();
let len = string2.len();
let capacity = string2.capacity();
println!("{}, {}, {}", unsafe { *ptr as char }, len, capacity); // d, 3, 3
// pointer to the first character points to letter d
// len is 3 characters long so 3
// string has now 3 bytes of space on the heap
string2.push_str("ghijk"); // we can mutate String type, capacity and length will aslo change
println!("{}, {}", string2, string2.capacity()); // defghijk, 8
} // memory of string2 on the heap will be freed here because owner goes out of scope
}