Rust所有权限制问题:已移动值复用的内存友好解决方案
问题描述
编译时遇到以下所有权错误:
error[E0382]: use of moved value: `updated_setting_values` --> swu3\src\data_processor\mod.rs:53:9 | 37 | let updated_setting_values = data_management( | ----------------------- move occurs because `updated_setting_values` has type `Vec<interfaces::inputs::constants::constants::SettingValues>`, which does not implement the `Copy` trait ... 52 | self.all_setting_values_in_memory = updated_setting_values; | ----------------------- value moved here 53 | updated_setting_values | ^^^^^^^^^^^^^^^^^^^^^^ value used here after move
相关代码如下:
pub struct DataProcessor { count_iterations: u8, all_setting_values_in_memory: Vec<SettingValues>, } impl DataProcessor { pub fn new() -> Self { Self { count_iterations: 0, all_setting_values_in_memory: vec![SettingValues::new()], } } pub fn process_step( &mut self, default_settings: &[DefaultSetting], mode_specific_values: &Vec<SettingValue>, current_mode: Mode, current_profile: ProfileId, reset_mode_flag: bool, profile_update_status: ProfileUpdate, stored_setting_values: &Vec<SettingValues>, ) -> Vec<SettingValues> { let is_initial_run = self.count_iterations < 3; let selected_values = if INTERNAL_MEMORY_SWITCH { &self.all_setting_values_in_memory } else { stored_setting_values }; let updated_setting_values = data_management( default_settings, selected_values, mode_specific_values, current_mode, current_profile, is_initial_run, reset_mode_flag, profile_update_status ); if self.count_iterations <= 3 { self.count_iterations += 1; } self.all_setting_values_in_memory = updated_setting_values; updated_setting_values } }
需求:self.all_setting_values_in_memory需要持有data_management的输出值,同时process_step要返回该值,且因内存限制不能使用clone方法。
解决方案
方案1:使用共享所有权(推荐,无数据复制)
将all_setting_values_in_memory的类型改为Rc<Vec<SettingValues>>,通过克隆Rc指针共享所有权,底层数据不会被复制,内存开销极小:
use std::rc::Rc; pub struct DataProcessor { count_iterations: u8, all_setting_values_in_memory: Rc<Vec<SettingValues>>, } impl DataProcessor { pub fn new() -> Self { Self { count_iterations: 0, all_setting_values_in_memory: Rc::new(vec![SettingValues::new()]), } } pub fn process_step( &mut self, default_settings: &[DefaultSetting], mode_specific_values: &Vec<SettingValue>, current_mode: Mode, current_profile: ProfileId, reset_mode_flag: bool, profile_update_status: ProfileUpdate, stored_setting_values: &Vec<SettingValues>, ) -> Rc<Vec<SettingValues>> { let is_initial_run = self.count_iterations < 3; let selected_values = if INTERNAL_MEMORY_SWITCH { &self.all_setting_values_in_memory } else { stored_setting_values }; // 将data_management的结果包裹在Rc中 let updated_setting_values = Rc::new(data_management( default_settings, selected_values, mode_specific_values, current_mode, current_profile, is_initial_run, reset_mode_flag, profile_update_status )); if self.count_iterations <= 3 { self.count_iterations += 1; } // 克隆Rc指针(仅复制指针和引用计数,不复制数据) self.all_setting_values_in_memory = updated_setting_values.clone(); updated_setting_values } }
方案2:返回内部引用(无需额外内存开销)
如果调用者不需要获取值的所有权,可修改函数返回类型为&Vec<SettingValues>,通过生命周期标注保证引用有效性:
pub fn process_step( &mut self, default_settings: &[DefaultSetting], mode_specific_values: &Vec<SettingValue>, current_mode: Mode, current_profile: ProfileId, reset_mode_flag: bool, profile_update_status: ProfileUpdate, stored_setting_values: &Vec<SettingValues>, ) -> &Vec<SettingValues> { let is_initial_run = self.count_iterations < 3; let selected_values = if INTERNAL_MEMORY_SWITCH { &self.all_setting_values_in_memory } else { stored_setting_values }; let updated_setting_values = data_management( default_settings, selected_values, mode_specific_values, current_mode, current_profile, is_initial_run, reset_mode_flag, profile_update_status ); if self.count_iterations <= 3 { self.count_iterations += 1; } self.all_setting_values_in_memory = updated_setting_values; // 返回self内部存储的引用 &self.all_setting_values_in_memory }
内容的提问来源于stack exchange,提问作者Js7
相关产品推荐
相关产品推荐

