Rust书指定:
使堆栈快速运行的另一个特性是堆栈上的所有数据必须占用已知的固定大小。
它还说String
存储在堆上,因为大小未知且可能会发生变异。
"复合"存储包含String
的数组等数据结构?阵列的大小是固定的,但阵列的组件大小可能会发生变化。
let array: [String; 3] = ["A","B","C"];
这种"复合"数据类型是否存储?
答案 0 :(得分:12)
<强>两个强>
术语点:在讨论类型的内存布局时,不应该谈论堆栈与堆,而是关于内联与离线 1 < / SUP>:
一个简单的例子,整数是内联存储的:
// i32
+---+
| 3 |
+---+
典型的struct Point { x: i32, y: i32 }
也以内联方式存储:
// Point
+---+---+
| x | y |
+---+---+
String
,通常表示为struct String { data: *mut u8, len: usize, cap: usize }
, 内联和离线存储:
// String
+-------+-------+-------+
| data | len | cap |
+-------+-------+-------+
|
\
+-------------+
|Hello, World!|
+-------------+
内联部分是3个指针的存储空间,而离线部分是一个堆分配的记录,其中包含字符串"Hello, World!"
的内容。
但是,内联并不总是意味着堆栈。一个Box<Point>
:
// Box<Point>
+-------+
| data |
+-------+
|
\
+---+---+
| x | y |
+---+---+
将其Point
(将其数据成员内联存储)存储在堆上!
同样,离线并不总是意味着堆:
fn main() {
let i = 3;
let r = &i;
}
此处,r
是一个引用(指针),指向i
,而i
位于堆栈中!
1 是的,我正在提出这个问题,我们将不胜感激。
所以,回到问题:
它还说
String
存储在堆上,因为大小未知且可能会发生变异。
这是一个近似值,如上所述String
有一些内联数据(指针,长度和容量),有些数据在堆上(字符串内容)。
“复合”数据结构(如包含
String
的数组)存储在哪里?数组的大小是固定的,但数组的组件大小可能会发生变化。let array: [String; 3] = ["A","B","C"];
它存储在堆栈和堆中:
// [String; 3]
+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| data | len | cap | data | len | cap | data | len | cap |
+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| | |
\ \ \
+-+ +-+ +-+
|A| |B| |C|
+-+ +-+ +-+
这是9个指针的内联数据(在堆栈中),以及堆上3个单独的分配。
存储此类“复合”数据类型的规则是什么?
数据成员总是内联,指针和引用可能指向离线数据,这些数据可能在堆上,堆栈上等......
答案 1 :(得分:3)
String
只包裹Vec<u8>
。所以这适用于所有Vecs
。
Vec
在堆栈上有一个固定的大小:它的长度,容量和指向存储实际内容的堆的指针。
所以在堆栈上有一个三个Strings
的数组意味着&#34;元数据&#34;这些字符串在堆栈上(长度,容量和指向数据的指针)。
这些字符串的实际数据虽然存储在堆上,因为正确识别时它的长度可变。