memory-management - 除了非文字进入堆之外,文字和非文字之间有什么区别?

标签 memory-management types rust

我对文字和非文字之间的区别感到困惑(堆上的那些,我不知道它们叫什么)。例如,taking the String type as an example :

We’ve already seen string literals, where a string value is hardcoded into our program. String literals are convenient, but they aren’t always suitable for every situation in which you want to use text. One reason is that they’re immutable. ...

我不明白上面的内容,因为我们已经看到了这样的例子:

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");

最佳答案

Clearly literals can be mutable in 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;
}

老实说,我不知道什么叫“非文字”。文字是一种特定类型的表达式,但程序中除了表达式之外还有其他类型的东西。这有点像说“猫”和“非猫”——第二组包括狗、蘑菇、沙子和/或情绪吗?


the fact that literals go into the stack, while non-literals go into the heap

这两种品质并没有直接关系。堆栈上有非文字是很容易的:

fn main() {
    let a = 1;
    let b = 2;
    let c = a + b;
}

所有三个变量都在堆栈上,但源代码中的任何地方都没有文字 3

现在,Rust 不允许字面量值具有堆分配,但这是一种特定于语言的东西,可能会随着时间的推移而改变。其他语言可能允许这样做。

事实上,在 Rust 中,你必须特意把一些东西放在堆上。 BoxVecString 等类型都调用函数来分配堆上的空间。您的代码使用堆内存的唯一方法是使用这些类型、使用它们的其他类型或以其他方式分配堆内存的类型。


What is the reason we cannot use String literal data-type

没有 String 文字——没有。源代码 "foo" 创建了一个类型为 &'static str 的文字。 These are drastically different types .具体来说,Rust 语言可以在没有堆的环境中工作;没有文字可以假设可以分配内存。

have to specifically use String::from()

String::from&str 转换为 String;它们是两种不同的类型,必须进行转换。

Clearly, as per the example, in my code, both can be mutable

,他们不能。不可能以 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# 字符串也是不可变的,但您可以重新分配一个变量以指向不同的不可变字符串。


另见:

关于memory-management - 除了非文字进入堆之外,文字和非文字之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48411196/

相关文章:

haskell - `to` 镜头进入 zipper

Scala 泛型方法。接受任何数值序列

rust - 如何在 Rust 中序列化 Arc<Mutex<T>>?

c - 为什么要在堆上而不是栈上分配内存?

objective-c - NSData initWithContentsOfURL : does not return the original allocation?

iOS 应用程序内存限制

rust - 我如何在 Rust 代码中表示 C 的 "unsigned negative"值?

java - App Engine : How does memory work?(将 Mahout 与 App Engine 结合使用)

C类型无法被正确识别

authentication - 如何创建具有基于 session 身份验证的 actix-web HttpServer?