我对文字和非文字之间的区别感到困惑(那些在堆上的,我不知道它们被称为什么)。例如,taking the String
type as an example:
我们已经看过字符串文字,字符串值是硬编码的 进入我们的计划。字符串文字很方便,但它们不是 始终适合您想要使用文本的每种情况。一 原因是他们是不可改变的。 ...
我不明白上述内容,因为我们已经看到过这样的例子:
let mut a = "a"; // this is String literal here, so sitting on the stack
a = "b";
println!("a is being changed to...{}", a); // this is the same String literal sitting on the stack?
显然,Rust中的文字可以变化。两者之间有什么区别,除了文字进入堆栈这一事实,而非文字进入堆?
我试图理解为什么我不应该在我的代码中使用可变文字,考虑到堆栈比堆快。
// a is mutable literal
let mut a = "a";
a = "b";
// b is mutable 'non-literal'
let mut b = String::from("a");
b = String::from("b");
答案 0 :(得分:12)
显然,文字在Rust中是可变的
首先,您需要了解what a literal is。文字从不可变,因为它们是字面上在源代码中编写并编译成最终的二进制文件。您的程序不会更改您的源代码!
显示您无法修改文字的示例:
fn main() {
1 += 2;
}
error[E0067]: invalid left-hand side expression
--> src/main.rs:2:5
|
2 | 1 += 2;
| ^ invalid expression for left-hand side
另一方面,可以将文字复制到变量中,然后可以更改变量,但我们仍然没有改变文字1
:
fn main() {
let mut a = 1;
a += 2;
}
说实话,我不知道我称之为“非文字”。文字是特定类型的表达式,但除了表达式之外,程序中还有其他类型的东西。这有点像说“猫”和“非猫” - 第二组是否包括狗,蘑菇,沙子和/或情感?
文字进入堆栈的事实,而非文字进入堆
这两个品质并不是真正直接相关的。在堆栈上使用非文字非常容易:
fn main() {
let a = 1;
let b = 2;
let c = a + b;
}
所有三个变量都在堆栈中,但源代码中的任何位置都没有文字3
。
现在,Rust不允许文字值具有堆分配,但这是一种特定于语言的事物,可能会随着时间的推移而发生变化。其他语言可能允许它。
事实上,你必须在Rust中不遗余力地把东西放在堆上。像Box
,Vec
和String
这样的类型都调用函数来在堆上分配空间。代码使用堆内存的唯一方法是使用这些类型,使用它们的其他类型,或者以其他方式分配堆内存的类型。
我们无法使用
的原因是什么String
文字数据类型
没有String
字面值 - 没有。源代码"foo"
创建了&'static str
类型的文字。 These are drastically different types。具体来说,Rust语言可以在没有堆的环境中工作;没有文字可以假设可以分配内存。
必须专门使用
String::from()
String::from
从&str
转换为String
;它们是两种不同的类型,必须进行转换。
显然,根据示例,在我的代码中,两者都可以是可变的
没有,他们不能。不可能从let mut foo = "a"
开始并修改“a”以成为其他任何东西。您可以更改foo
指向的内容:
let mut foo = "a";
foo
+-----------+
|
|
+---v---+
| |
| "a" |
| |
+-------+
foo = "b";
foo
+----------+
|
|
+-------+ +---v---+
| | | |
| "a" | | "b" |
| | | |
+-------+ +-------+
"a"
和"b"
都不会更改,但foo
指向的内容。
此并非特定于Rust 。例如,Java和C#字符串也是不可变的,但您可以重新分配变量以指向不同的不可变字符串。
另见: