我们在所有权中阅读了函数如何将其参数数据保留在堆栈中。在原始类型的情况下,这可能是一个值,或者是指向堆中驻留的数据的指针。现在,当引用某个东西时,该参数如何在堆栈中表示?
在内部,引用(即&'a T
基本上只是一个指针)。区别在于您Rust
的静态编译规则保证了内存的安全性。同样,您在本章中刚刚阅读的规则。当您将参数传递给时,说一个具有如下签名的函数:
struct UnitBar(i32);
fn foo(data: &UnitBar);
Run Code Online (Sandbox Code Playgroud)
您这样称呼它:
struct UnitBar(i32);
fn main() {
let bar = UnitBar(0); //Sizeof bar is sizeof i32
foo(&bar);
}
Run Code Online (Sandbox Code Playgroud)
UnitBar
在这种情况下,Rust将分配一个4字节的a 。然后,它将分配一个指向的指针bar
,该指针的大小与计算机中的本机指针大小相同,或更习惯上与usize
in rust 相同。请注意,在内存级别,指针和引用之间没有区别。在静态编译级别或您的代码中,会进行静态编译时检查,以确保您的代码遵循rust的规则。从这里开始,data
参数in fn foo
将表示为内存中的指针。每次传递给另一个函数或作用域时,这都不会复制它指向的数据。
尽管不能保证看起来像这样,但由于编译器可以在内存中四处移动以生成更高效的程序,因此这几乎是它的工作方式。
附带说明一下,有3种特殊情况:
&[T]
将需要两个“指针长度”来存储。为什么?因为a &[T]
是一种特殊类型,所以其中包含a *const T
和a usize
。这是c的等效项:struct SliceReference {
*const T data;
size_t length;
}
Run Code Online (Sandbox Code Playgroud)
&str
。这本质上是a &[u8]
,因此它也遵循上面的内存模型,但是向您保证它包含的所有字符(即,存储在其中的字节配置)都是UTF-8。&dyn std::fmt::Debug
。对于c / c ++程序员,其大小再次为2 usize
或2 size_t
s。第一个指针指向数据,第二个指针指向vtable,其中存储了每个函数各自的函数签名。请注意,以上所有内容均与&T
内存中的内容基本相同:
Option<&T> -|
Box<T> |
Rc<T> - These all have the same size as `&T`
Arc<Mutex<T>> |
struct Foo(&T) -|
Run Code Online (Sandbox Code Playgroud)
作为编辑,这里证明它们都是相同的大小。
归档时间: |
|
查看次数: |
54 次 |
最近记录: |