@@ -868,108 +868,27 @@ fn first((value, _): (int, float)) -> int { value }
868868
869869# Destructors
870870
871- C-style resource management requires the programmer to match every allocation
872- with a free, which means manually tracking the responsibility for cleaning up
873- ( the owner). Correctness is left to the programmer, and it's easy to get wrong .
871+ A * destructor * is a function responsible for cleaning up the resources used by
872+ an object when it is no longer accessible. Destructors can be defined to handle
873+ the release of resources like files, sockets and heap memory .
874874
875- The following code demonstrates manual memory management, in order to contrast
876- it with Rust's resource management. Rust enforces safety, so the ` unsafe `
877- keyword is used to explicitly wrap the unsafe code. The keyword is a promise to
878- the compiler that unsafety does not leak outside of the unsafe block, and is
879- used to create safe concepts on top of low-level code.
875+ Objects are never accessible after their destructor has been called, so there
876+ are no dynamic failures from accessing freed resources. When a task fails, the
877+ destructors of all objects in the task are called.
880878
881- ~~~~
882- use core::libc::{calloc, free, size_t};
883-
884- fn main() {
885- unsafe {
886- let a = calloc(1, int::bytes as size_t);
887-
888- let d;
879+ The ` ~ ` sigil represents a unique handle for a memory allocation on the heap:
889880
890- {
891- let b = calloc(1, int::bytes as size_t);
892-
893- let c = calloc(1, int::bytes as size_t);
894- d = c; // move ownership to d
895-
896- free(b);
897- }
898-
899- free(d);
900- free(a);
901- }
902- }
903881~~~~
904-
905- Rust uses destructors to handle the release of resources like memory
906- allocations, files and sockets. An object will only be destroyed when there is
907- no longer any way to access it, which prevents dynamic failures from an attempt
908- to use a freed resource. When a task fails, the stack unwinds and the
909- destructors of all objects owned by that task are called.
910-
911- The unsafe code from above can be contained behind a safe API that prevents
912- memory leaks or use-after-free:
913-
914- ~~~~
915- use core::libc::{calloc, free, c_void, size_t};
916-
917- struct Blob { priv ptr: *c_void }
918-
919- impl Blob {
920- fn new() -> Blob {
921- unsafe { Blob{ptr: calloc(1, int::bytes as size_t)} }
922- }
923- }
924-
925- impl Drop for Blob {
926- fn finalize(&self) {
927- unsafe { free(self.ptr); }
928- }
929- }
930-
931- fn main() {
932- let a = Blob::new();
933-
934- let d;
935-
936- {
937- let b = Blob::new();
938-
939- let c = Blob::new();
940- d = c; // move ownership to d
941-
942- // b is destroyed here
943- }
944-
945- // d is destroyed here
946- // a is destroyed here
882+ {
883+ // an integer allocated on the heap
884+ let y = ~10;
947885}
886+ // the destructor frees the heap memory as soon as `y` goes out of scope
948887~~~~
949888
950- This pattern is common enough that Rust includes dynamically allocated memory
951- as first-class types (` ~ ` and ` @ ` ). Non-memory resources like files are cleaned
952- up with custom destructors.
953-
954- ~~~~
955- fn main() {
956- let a = ~0;
957-
958- let d;
959-
960- {
961- let b = ~0;
962-
963- let c = ~0;
964- d = c; // move ownership to d
965-
966- // b is destroyed here
967- }
968-
969- // d is destroyed here
970- // a is destroyed here
971- }
972- ~~~~
889+ Rust includes syntax for heap memory allocation in the language since it's
890+ commonly used, but the same semantics can be implemented by a type with a
891+ custom destructor.
973892
974893# Ownership
975894
@@ -984,6 +903,22 @@ and destroy the contained object when they go out of scope. A box managed by
984903the garbage collector starts a new ownership tree, and the destructor is called
985904when it is collected.
986905
906+ ~~~~
907+ // the struct owns the objects contained in the `x` and `y` fields
908+ struct Foo { x: int, y: ~int }
909+
910+ {
911+ // `a` is the owner of the struct, and thus the owner of the struct's fields
912+ let a = Foo { x: 5, y: ~10 };
913+ }
914+ // when `a` goes out of scope, the destructor for the `~int` in the struct's
915+ // field is called
916+
917+ // `b` is mutable, and the mutability is inherited by the objects it owns
918+ let mut b = Foo { x: 5, y: ~10 };
919+ b.x = 10;
920+ ~~~~
921+
987922If an object doesn't contain garbage-collected boxes, it consists of a single
988923ownership tree and is given the ` Owned ` trait which allows it to be sent
989924between tasks. Custom destructors can only be implemented directly on types
@@ -1007,7 +942,7 @@ refer to that through a pointer.
1007942## Owned boxes
1008943
1009944An owned box (` ~ ` ) is a uniquely owned allocation on the heap. It inherits the
1010- mutability and lifetime of the owner as it would if there was no box.
945+ mutability and lifetime of the owner as it would if there was no box:
1011946
1012947~~~~
1013948let x = 5; // immutable
@@ -1021,8 +956,8 @@ let mut y = ~5; // mutable
1021956
1022957The purpose of an owned box is to add a layer of indirection in order to create
1023958recursive data structures or cheaply pass around an object larger than a
1024- pointer. Since an owned box has a unique owner, it can be used to represent any
1025- tree data structure.
959+ pointer. Since an owned box has a unique owner, it can only be used to
960+ represent a tree data structure.
1026961
1027962The following struct won't compile, because the lack of indirection would mean
1028963it has an infinite size:
@@ -1092,7 +1027,6 @@ d = b; // box type is the same, okay
10921027c = b; // error
10931028~~~~
10941029
1095-
10961030# Move semantics
10971031
10981032Rust uses a shallow copy for parameter passing, assignment and returning values
0 commit comments