当一个函数的参数作为参数引用时,它究竟分配给函数的堆栈?

问题描述 投票:2回答:1

我们在Ownership中读取函数如何将其参数数据保存在堆栈中。对于原始类型或指向驻留在堆上的数据的指针,这可能是一个值。现在,当参数是什么时,参数如何在堆栈中表示?

rust
1个回答
4
投票

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

struct UnitBar(i32);
fn foo(data: &UnitBar);

你这么称呼它:

struct UnitBar(i32);
fn main() {
    let bar = UnitBar(0); //Sizeof bar is sizeof i32
    foo(&bar);
}

Rust会分配一个UnitBar,在这种情况下是4个字节。然后,它将分配一个指向bar的指针,该指针与计算机中的本机指针大小相同,或更加惯用于与生锈中的usize相同的大小。请注意,指针和内存级别的引用之间没有区别。在静态编译级别或代码中,有静态编译时检查以确保您的代码遵循rust的规则。从这里开始,data中的fn foo参数将表示为内存中的指针。每次将数据传递给另一个函数或作用域时,它都不会复制它指向的数据。

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


作为旁注,有3个特例:

  1. 切片的情况。 &[T]将采用两个“指针长度”来存储。为什么?因为&[T]是一种特殊的类型,它包含*const Tusize。这是相当于这个的c:
struct SliceReference {
    *const T data;
    size_t length;
}
  1. 另一个(类似案例)是&str。这本质上是一个&[u8],所以它也遵循上面的内存模型,而是向你保证它包含的所有字符,即存储在其中的字节配置,都是UTF-8。
  2. 这是最后一种情况,其中有特征对象。即,&dyn std::fmt::Debug。对于c / c ++程序员来说,这个大小又是两个usizes或两个size_ts。存在指向数据的第一指针,第二指针指向存储其各自功能的功能签名的vtable。

请注意,以上所有内容都与内存中与&T基本相同的内容相关:

Option<&T>     -|
Box<T>          |
Rc<T>           - These all have the same size as `&T`
Arc<Mutex<T>>   |
struct Foo(&T) -|

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

© www.soinside.com 2019 - 2024. All rights reserved.