rust 是如何处理返回值的

Kaz*_*zik 0 runtime rust

我对我的代码有疑问:

pub fn get_signals(path: &String) -> Vec<Vec<f64>> {
    let mut rdr = csv::ReaderBuilder::new().delimiter(b';').from_path(&path).unwrap();

    let mut signals: Vec<Vec<f64>> = Vec::new();

    for record in rdr.records(){
        let mut r = record.unwrap();
        for (i, value) in r.iter().enumerate(){
            match signals.get(i){
                Some(_) => {},
                None    => signals.push(Vec::new())
            }
            signals[i].push(value.parse::<f64>().unwrap());
        }
    }

    signals
}
Run Code Online (Sandbox Code Playgroud)

Rust 究竟是如何处理返回的?例如,当我写时let signals = get_signal(&"data.csv".to_string());,Rust 是否假设我想要一个新的 Vec 实例(复制所有数据),或者只是传递一个指向先前分配(通过Vec::new())内存的指针?执行此操作的最有效方法是什么?另外,会发生什么rdr?我认为,鉴于 Rusts 内存安全,它已被销毁。

Mat*_* M. 6

Rust 究竟是如何处理返回的?

Rust 语言做出的唯一保证是,如果代码中没有明确的内容,值永远不会被克隆.clone()。因此,从语义的角度来看,移动值不需要分配内存。

Rust 是否假设我想要一个Vec(复制所有数据)的新实例,或者只是传递一个指向先前分配(通过Vec::new())内存的指针?

这是特定于实现的,并且是 ABI(应用程序二进制接口)的一部分。Rust ABI不是形式化的,也不稳定,所以没有描述它的标准,也不能保证这种情况。

此外,这将取决于函数调用是否是内联还是没有。如果函数调用被内联,当然return不再有相同的行为应该被观察到。

对于小值,它们应该通过一个寄存器(或几个寄存器)返回。

对于较大的值

  • 调用者应该在堆栈上保留内存(适当大小和对齐)并将指向该区域的指针传递给被调用者,
  • 然后被调用者将在指向的地方构造返回值,这样当它返回时,该值存在于那里供调用者使用。

注意:这里的大小是栈上的大小,由std::mem::size_of;返回。等等size_of::<Vec<_>>() == 2464 位架构。

执行此操作的最有效方法是什么?

返回与单个调用一样有效。

但是,如果您发现自己处于这样一种情况,例如,您想逐行读取文件,那么从一个调用到另一个调用重用缓冲区是有意义的,这可以通过以下任一方式完成:

  • 采取&mut引用到缓冲区(String或者Vec<u8>说)
  • 或按值获取缓冲区并返回它。

重点是避免内存分配。