Rust 当函数的堆栈中有一个对变量的引用作为其参数时,到底分配给它的是什么?

Rust 当函数的堆栈中有一个对变量的引用作为其参数时,到底分配给它的是什么?,rust,Rust,我们了解了函数如何将其参数数据保存在堆栈中。这可能是基元类型的值,也可能是指向堆上数据的指针。现在,当参数是对某物的引用时,它在堆栈中是如何表示的呢?在内部,引用,即&'T基本上只是一个指针。不同之处在于,Rust的静态编译规则保证了内存安全。就像你刚才在那一章读到的规则一样。当您将参数传递给时,比如一个具有如下签名的函数: struct-UnitBar(i32); fn foo(数据:&UnitBar); 你这样称呼它: struct-UnitBar(i32); fn main(){ 设ba

我们了解了函数如何将其参数数据保存在堆栈中。这可能是基元类型的值,也可能是指向堆上数据的指针。现在,当参数是对某物的引用时,它在堆栈中是如何表示的呢?

在内部,引用,即
&'T
基本上只是一个指针。不同之处在于,
Rust
的静态编译规则保证了内存安全。就像你刚才在那一章读到的规则一样。当您将参数传递给时,比如一个具有如下签名的函数:

struct-UnitBar(i32);
fn foo(数据:&UnitBar);
你这样称呼它:

struct-UnitBar(i32);
fn main(){
设bar=UnitBar(0);//Sizeof bar是Sizeof i32
foo&bar;
}
Rust将分配一个
UnitBar
,在本例中为4字节。然后,它将分配一个指向
的指针,该指针的大小与计算机中的本机指针相同,或者更习惯地说与rust中的usize相同。请注意,在内存级别上,指针和引用之间没有区别。在静态编译级别,或者在代码中,存在静态编译时检查,以确保代码遵循rust的规则。从这里开始,
fn foo
中的
data
参数将表示为内存中的指针。此不会在每次传递到另一个函数或作用域时复制它所指向的数据

虽然不能保证看起来像这样,因为编译器可以在内存中移动东西以生成更高效的程序,但这就是它的工作原理


作为旁注,有3种特殊情况:

  • 切片的情况<代码>&[T]将需要两个“指针长度”来存储。为什么?因为
    &[T]
    是一种特殊类型,其中包含
    *const T
    usize
    。它是这个的c等价物:
  • 另一个(类似的情况)是
    &str
    。这本质上是一个
    &[u8]
    ,因此它也遵循上面的内存模型,但可以确保它包含的所有字符(即其中存储的字节配置)都是UTF-8
  • 这是最后一种情况,其中有trait对象。即,
    &dyn std::fmt::Debug
    。对于c/c++程序员来说,它的大小也是两个
    usize
    s或两个
    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) -|
    
    选项-|
    盒子|
    Rc-这些都与`&T的大小相同`
    弧|
    结构Foo&T-|
    


    作为编辑,是这些指针大小相同的证明。

    您确定智能指针(
    Rc
    Arc
    ,等等)的大小与
    &T
    相同吗?除了封装的数据,它们都有额外的状态。@apemanzilla是的,一开始我会相信,但奇怪的是,它们的大小是一样的。请看我发布的编辑。@apemanzilla
    Rc
    Arc
    将refcount存储在“框”中,与
    T
    对齐。它们没有独立的数据指针和ReCube指针,就像C++中的代码> SyddYPPT/<代码>中所看到的。注意:你的3个特殊情况通常被称为动态大小的类型。无法保证DST的布局,过去有人建议将
    和(Add+Sub)
    表示为两个v-ptr+一个数据ptr。
    Option<&T>     -|
    Box<T>          |
    Rc<T>           - These all have the same size as `&T`
    Arc<Mutex<T>>   |
    struct Foo(&T) -|