I have narrowed down my real life Rust code to the following:
use std::fs::File;
use std::io::{BufRead, BufReader};
struct FileHandler {
input_file: File,
}
impl FileHandler {
fn setup(in_file_name: &str) -> Self {
let i_file = File::open(in_file_name).unwrap();
Self { input_file: i_file }
}
}
fn process_file(files: &FileHandler) {
let lines = BufReader::new(files.input_file).lines();
for _ln in lines {
println!("one more line");
}
}
fn main() {
let files = FileHandler::setup("foo.txt");
process_file(&files);
}
It does not compile with the message:
cannot move out of `files.input_file` which is behind a shared reference
--> demo.rs:16:32
|
16 | let lines = BufReader::new(files.input_file).lines();
| ^^^^^^^^^^^^^^^^ move occurs because `files.input_file` has type `File`, which does not implement the `Copy` trait
But precisely, I don't want to make a copy. I just want to use the file I have already checked to be correct. I have tried with mutable references and fields. Same error.
As the error implies, BufReader::new
is attempting to move files.input_files
, which is behind a shared reference ( &FileHandler
). In order to have it not move files.input_file
, use a reference to it instead:
use std::fs::File;
use std::io::{BufRead, BufReader};
struct FileHandler {
input_file: File,
}
impl FileHandler {
fn setup(in_file_name: &str) -> Self {
let i_file = File::open(in_file_name).unwrap();
Self { input_file: i_file }
}
}
fn process_file(files: &FileHandler) {
// --- CHANGED ---
let lines = BufReader::new(&files.input_file).lines();
for _ln in lines {
println!("one more line");
}
}
fn main() {
let files = FileHandler::setup("foo.txt");
process_file(&files);
}
This happens because BufReader is generic. If you give it a value, it will move it, if you give it a reference it'll just use the reference instead. Take a look at " Understanding Ownership " from The Book for more information on how ownership works.
let files = FileHandler::setup("foo.txt");
This creates a FileHandler
struct which stores another struct called File
in input_file
property.
files
struct has the ownership of it's properties. So files
owns input_file
.
If you directly use that input_file
property like this:
some_function(files.input_file);
This means input_file
's ownership will be moved to that function.
But if you do this then what happens if I try to access files.input_file
again? Maybe inside of some_function
, the struct stored in input_file
property destroyed?
So I can't use it anymore like files.input_file
.
Use the reference of input_file
, so it is borrowed , not moved :
some_function(&files.input_file);
Or in this case of yours:
BufReader::new(&files.input_file);
(btw IMHO I can suggest that you can use new
instead of setup
. Creating a struct with some settings often managed by a new
function. FileHandler::new()
is much more familiar to Rust devs. Like BufReader::new()
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.