首页 > 解决方案 > 在 2 个结构之间共享变量

问题描述

我是 Rust 新手,想在变量之间共享内存。我收到关于参考的错误

use std::collections::HashMap;

struct File {
  file_name: String,
  max_value: Vec<f32>,
}

struct FileHolder<'a> {
  file_holder_name: String,
  first_value: HashMap<String, &'a f32>,
  last_value: HashMap<String, &'a f32>,
}

fn get_file() -> File {
  let x = vec![1f32, 2f32, 3f32, 4f32, 5f32];
  let file = File { file_name: String::from("F1"), max_value: x };
  file
}

fn get_files() -> Vec<File> {
  let file1 = get_file();
  let file2 = get_file();
  let file3 = get_file();
  let file4 = get_file();
  let files = vec![file1, file2, file3, file4];
  files
}

fn transfer_to_holder(files: &Vec<File>) -> HashMap<usize, FileHolder> {

  let mut file_holders = HashMap::new();

  for i in 0..3 {
    let mut file_holder = FileHolder {
      file_holder_name: String::from("FH1"),
      first_value: HashMap::new(),
      last_value: HashMap::new()
    };
    file_holders.insert(i,file_holder);
  }
  
  files.iter().map(|file| {
    file_holders.iter_mut().map(|(sensor_index, file_holder_temp)| {
      file_holder_temp.first_value.insert(file.file_name.to_string(), &file.max_value[0]);
      file_holder_temp.last_value.insert(file.file_name.to_string(), &file.max_value[4]);
    })
  });
      
  
//   for file in files {
//     let i = 0;
//     let mut file_holder_temp = file_holders.get_mut(&i).unwrap();
//     file_holder_temp.first_value.insert(file.file_name.to_string(), &file.max_value[0]);
//     file_holder_temp.first_value.insert(file.file_name.to_string(), &file.max_value[4]);
//   }
  file_holders
}

fn main() {
  let files = get_files();
  let file_holder = transfer_to_holder(&files);
}

更新:有错误的旧代码:

use std::collections::HashMap;

Struct File {
  file_name: String,
  value: Vec<f32>
}

Struct FileHolder {
  file_holder_name:String,
  first_value: HashMap<String, &f32>,
  last_value: HashMap<String, &f32>
}

fn get_file()->File {
  let x = [1,2,3,4,5];
  let file = File { file_name: String::from("F1"), value: x };
  return file;
}

fn get_files() -> Vec<File> {
  let file1 = get_file();
  let file2 = get_file();
  let file3 = get_file();
  let file4 = get_file();
  let files = Vec[file1, file2, file3, file4];
  return files;
}

fn trasfer_to_holder(files: &Vec<File>) -> FileHolder {
  let file_holder = FileHolder {
    file_holder_name: String::from("FH1"),
    first_value: HashMap::new(),
    last_value: HashMap::new()
  }
  for file in Files {
    file_holder.first_value.insert(file.file_name, &file.value[0]);
    file_holder.last_value.insert(file.file_name, &file.value[4]);
  }
  return file_holder;
}

fn main() {
  let files = get_files();
  let file_holder = trasfer_to_holder(&files);
}

以下是错误:

cannot borrow `file_holder.first_value` as mutable, as it is behind a `&` reference

在这个例子中,我只有 5 个文件;但是,在我的真实案例中,我有大约 150000 个文件。如果我再次将 150000first_value和 150000存储在 中,那就是资源浪费。因此,如果我参考第一个结构的参考,那就太好了。我尝试了多种方法;玩了一辈子,但对于初学者来说很难理解。last_valueFileHolder

注意:文件file_holder一旦创建就永远不会更改;代码中可能有一些错误。

标签: rustreferenceimmutabilityownershipborrowing

解决方案


您提供的示例有一堆无效的语法,并且其中至少有十几个编译错误。清理它后,我能够编译该示例而没有任何问题:

use std::collections::HashMap;

struct File {
  file_name: String,
  max_value: Vec<f32>,
}

struct FileHolder<'a> {
  file_holder_name: String,
  first_value: HashMap<String, &'a f32>,
  last_value: HashMap<String, &'a f32>,
}

fn get_file() -> File {
  let x = vec![1f32, 2f32, 3f32, 4f32, 5f32];
  let file = File { file_name: String::from("F1"), max_value: x };
  file
}

fn get_files() -> Vec<File> {
  let file1 = get_file();
  let file2 = get_file();
  let file3 = get_file();
  let file4 = get_file();
  let files = vec![file1, file2, file3, file4];
  files
}

fn transfer_to_holder(files: &[File]) -> FileHolder {
  let mut file_holder = FileHolder {
    file_holder_name: String::from("FH1"),
    first_value: HashMap::new(),
    last_value: HashMap::new()
  };
  for file in files {
    file_holder.first_value.insert(file.file_name.to_string(), &file.max_value[0]);
    file_holder.first_value.insert(file.file_name.to_string(), &file.max_value[4]);
  }
  file_holder
}

fn main() {
  let files = get_files();
  let file_holder = transfer_to_holder(&files);
}

操场

此外,您为“节省空间”所做的努力实际上会适得其反,因为在所有系统&f32上,如果不是f32. 在操场环境中, an&f32确实是 an 的两倍f32

fn main() {
  dbg!(std::mem::size_of::<f32>()); // prints "4" bytes
  dbg!(std::mem::size_of::<&f32>()); // prints "8" bytes
}

操场

因此,您可以同时节省空间、简化代码、摆脱引用和生命周期注释,然后就这样做:

use std::collections::HashMap;

struct File {
  file_name: String,
  max_value: Vec<f32>,
}

struct FileHolder {
  file_holder_name: String,
  first_value: HashMap<String, f32>,
  last_value: HashMap<String, f32>,
}

fn get_file() -> File {
  let x = vec![1f32, 2f32, 3f32, 4f32, 5f32];
  let file = File { file_name: String::from("F1"), max_value: x };
  file
}

fn get_files() -> Vec<File> {
  let file1 = get_file();
  let file2 = get_file();
  let file3 = get_file();
  let file4 = get_file();
  let files = vec![file1, file2, file3, file4];
  files
}

fn transfer_to_holder(files: &[File]) -> FileHolder {
  let mut file_holder = FileHolder {
    file_holder_name: String::from("FH1"),
    first_value: HashMap::new(),
    last_value: HashMap::new()
  };
  for file in files {
    file_holder.first_value.insert(file.file_name.to_string(), file.max_value[0]);
    file_holder.first_value.insert(file.file_name.to_string(), file.max_value[4]);
  }
  file_holder
}

fn main() {
  let files = get_files();
  let file_holder = transfer_to_holder(&files);
}

操场


推荐阅读