The Drop Trait
Drop is a special goodbye method Rust calls automatically right before a value disappears for good.In this page:
impl Drop for Name {
fn drop(&mut self) {
// cleanup
}
}
Implementing Drop
Implementing the Drop trait's drop method lets a type execute custom cleanup code automatically the moment its value's scope ends.
Example: Implementing Drop
// Define a struct `Logger` to group related fields together
struct Logger {
name: String,
}
// Implement the `Drop` trait for `Logger`
impl Drop for Logger {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Logger '{}' shutting down" to the console, substituting in `self.name` (with a trailing newline)
println!("Logger '{}' shutting down", self.name);
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `_logger`, set to `Logger { name: String::from("main-logger") }`
let _logger = Logger { name: String::from("main-logger") };
// Print "Logger is active" to the console (with a trailing newline)
println!("Logger is active");
}
Login to try C/C++/Java/PHP code in the editor
Forcing an Early Drop
Since calling .drop() directly is disallowed by the compiler, std::mem::drop(value) is used to force a value to be cleaned up earlier than the end of its natural scope.
Example: Forcing an Early Drop
// Define a struct `Resource` to group related fields together
struct Resource;
// Implement the `Drop` trait for `Resource`
impl Drop for Resource {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Resource cleaned up" to the console (with a trailing newline)
println!("Resource cleaned up");
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `res`, set to `Resource`
let res = Resource;
// Print "About to drop early" to the console (with a trailing newline)
println!("About to drop early");
drop(res);
// Print "Dropped; continuing" to the console (with a trailing newline)
println!("Dropped; continuing");
}
Login to try C/C++/Java/PHP code in the editor
Drop Order Matches Reverse Declaration
When several values with Drop implementations go out of scope together, they are cleaned up in the reverse order they were declared, similar to unwinding a stack.
Example: Drop Order Matches Reverse Declaration
// Define a struct `Item` to group related fields together
struct Item(i32);
// Implement the `Drop` trait for `Item`
impl Drop for Item {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Dropping item {}" to the console, substituting in `self.0` (with a trailing newline)
println!("Dropping item {}", self.0);
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `_a`, set to `Item(1)`
let _a = Item(1);
// Declare an immutable variable `_b`, set to `Item(2)`
let _b = Item(2);
// Declare an immutable variable `_c`, set to `Item(3)`
let _c = Item(3);
// Print "All items created" to the console (with a trailing newline)
println!("All items created");
}
Login to try C/C++/Java/PHP code in the editor
A Practical Use: Resource Cleanup
Drop is commonly used to guarantee cleanup logic, like closing a connection, always runs -- even if the function returns early -- since the value is dropped whenever its scope ends.
Example: A Practical Use: Resource Cleanup
// Define a struct `Connection` to group related fields together
struct Connection {
id: u32,
}
// Implement the `Drop` trait for `Connection`
impl Drop for Connection {
// Define the function `drop` taking `self`
fn drop(&mut self) {
// Print "Closing connection #{}" to the console, substituting in `self.id` (with a trailing newline)
println!("Closing connection #{}", self.id);
}
}
// Define the function `use_connection` with no parameters
fn use_connection() {
// Declare an immutable variable `_conn`, set to `Connection { id: 7 }`
let _conn = Connection { id: 7 };
// Print "Using connection #7" to the console (with a trailing newline)
println!("Using connection #7");
}
// Entry point: execution of the program starts here
fn main() {
use_connection();
// Print "Connection was closed automatically" to the console (with a trailing newline)
println!("Connection was closed automatically");
}
Login to try C/C++/Java/PHP code in the editor
- Trying to call
.drop()directly on a value -- Rust forbids this explicitly and providesstd::mem::dropinstead. - Assuming
Drop::dropruns immediately when a value is moved -- it only runs when the value's owner truly goes out of scope. - Forgetting values are dropped in reverse declaration order within the same scope, which can matter for cleanup ordering.
- Implementing
Droplets a type run custom cleanup logic automatically when its value goes out of scope. - You cannot call the
dropmethod directly; use the free functionstd::mem::drop(value)to force an early drop. - Values are dropped in reverse order of their declaration within a scope.
Dropis commonly used for releasing resources like file handles, locks, or network connections.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: