pointers - How does Rust know which types own resources? -
when 1 has box pointer heap-allocated memory, assume rust has 'hardcoded' knowledge of ownership, when ownership transferred calling function, resources moved , argument in function new owner.
however, how happen vectors example? 'own' resources, , ownership mechanics apply box pointers -- yet regular values stored in variables themselves, , not pointers. how rust (know to) apply ownership mechanics in situation?
can make own type owns resources?
tl;dr: "owning" types in rust not magic , not hardcoded compiler or language. types written in way (do not implement copy
, have destructor) , have semantics enforced through non-copyability , destructor.
in core rust's ownership mechanism simple , has simple rules.
first of all, let's define move is. simple - value said moved when becomes available under new name , stops being available under old name:
struct x(u32); let x1 = x(12); let x2 = x1; // x1 no longer accessible here, trying use cause compiler error
same thing happens when pass value function:
fn do_something(x: x) {} let x1 = x(12); do_something(x1); // x1 no longer accessible here
note there absolutely no magic here - default every value of every type behaves in above examples. values of each struct or enum or else creates default moved.
another important thing can give every type destructor, is, piece of code invoked when value of type goes out of scope , destroyed. example, destructors associated vec
or box
free corresponding piece of memory. destructors can declared implementing drop
trait:
struct x(u32); impl drop x { fn drop(&mut self) { println!("dropping {}", x.0); } } { let x1 = x(12); } // x1 dropped here, , "dropping 12" printed
there way opt-out of non-copyability implementing copy
trait marks type automatically copyable - values no longer moved copied:
#[derive(copy, clone)] struct x(u32); let x1 = x(12); let x2 = x1; // x1 still available here
the copy done bytewise - x2
contain byte-identical copy of x1
.
not every type can made copy
- have copy
interior , do not implement drop
. primitive types (except &mut
references including *const
, *mut
raw pointers) copy
in rust, each struct contains primitives can made copy
. on other hand, structs vec
or box
not copy
- deliberately not implement because bytewise copy of them lead double frees because destructors can run twice on same pointer.
the copy
bit above slight digression on side, give clearer picture. ownership in rust based on move semantics. when value own something, in "box<t>
owns given t
", mean semantic connection between them, not magical or built language. such values vec
or box
not implement copy
, moved instead of copied, , (optionally) have destructor cleans these types may have allocated them (memory, sockets, files, etc.).
given above, of course can write own "owning" types. 1 of cornerstones of idiomatic rust, , lot of code in standard library , external libraries written in such way. example, c apis provide functions creating , destroying objects. writing "owning" wrapper around them easy in rust , close you're asking for:
extern { fn create_widget() -> *mut widgetstruct; fn destroy_widget(w: *mut widgetstruct); fn use_widget(w: *mut widgetstruct) -> u32; } struct widget(*mut widgetstruct); impl drop widget { fn drop(&mut self) { unsafe { destroy_widget(self.0); } } } impl widget { fn new() -> widget { widget(unsafe { create_widget() }) } fn use_it(&mut self) -> u32 { unsafe { use_widget(self.0) } } }
now can widget
owns foreign resource represented *mut widgetstruct
.
Comments
Post a Comment