文字和非文字有什么区别,除了非文字进入堆的事实?

时间:2018-01-23 21:33:53

标签: memory-management types rust

我对文字和非文字之间的区别感到困惑(那些在堆上的,我不知道它们被称为什么)。例如,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");

1 个答案:

答案 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中不遗余力地把东西放在堆上。像BoxVecString这样的类型都调用函数来在堆上分配空间。代码使用堆内存的唯一方法是使用这些类型,使用它们的其他类型,或者以其他方式分配堆内存的类型。

  

我们无法使用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#字符串也是不可变的,但您可以重新分配变量以指向不同的不可变字符串。

另见: