9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
fn print_sum(v: Vec<i32>) {
println!("{}", v[0] + v[1]);
// v is dropped and deallocated here
}
fn main() {
let mut v = Vec::new(); // creating the resource
for i in 1..1000 {
v.push(i);
}
// at this point, v is using
// no less than 4000 bytes of memory
// -------------------
// transfer ownership to print_sum:
print_sum(v);
// we no longer own nor anyhow control v
// it would be a compile-time error to try to access v here
println!("We're done");
// no deallocation happening here,
// because print_sum is responsible for everything
}
We are going to explain the memory management in the given Rust code.
The code demonstrates ownership and how it is transferred (moved) to a function.
Steps:
1. In main, a vector v is created and filled with integers from 1 to 999.
2. The vector v is then passed to the function print_sum .
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 1/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
3. Ownership of the vector is moved to print_sum , meaning that main can no longer use v .
4. print_sum prints the sum of the first two elements and then drops the vector, freeing the memory.
5. After the function call, main prints "We're done".
Memory details:
The vector in Rust is a heap-allocated data structure. When we push elements, it grows and may reallocate.
The memory of the vector is freed when it is dropped (i.e., when the function print_sum ends).
Let's break down the code with comments:
The provided Rust code demonstrates ownership and memory management in Rust:
1. Memory Allocation:
Vec::new() creates an empty vector. As elements are pushed, it dynamically allocates memory on the heap (growing as
needed).
2. Ownership Transfer:
v is moved to print_sum when passed as an argument. After this, main can no longer use v (compile-time error if
attempted).
3. Memory Deallocation:
The vector is dropped automatically at the end of print_sum , freeing its heap memory. This prevents leaks without
manual cleanup.
4. Key Observations:
No explicit deallocation is needed; Rust's ownership model handles memory safety.
The vector's memory is freed immediately after print_sum executes, not at the end of main .
Output:
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 2/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
The sum of the first two elements (1 + 2 = 3) is printed.
"We're done" prints afterward, confirming main completed without owning the vector.
This exemplifies Rust's zero-cost abstractions: memory management is enforced at compile time, avoiding runtime overhead.
if I want to copy variable what should I do?
We are going to show how to copy the vector instead of moving it.
There are two main ways:
1. Implement the Clone trait and use the .clone() method (if the type implements Clone).
2. For types that implement Copy, assignment copies the data. But note: Vec does not implement Copy because it owns heap data.
Since Vec<i32> does not implement Copy, we use .clone().
Alternatively, we can pass a reference to the function if we don't need a full copy (borrowing).
Let's demonstrate both:
Option 1: Cloning the vector (so we have two independent vectors)
Option 2: Borrowing (passing a reference) so that print_sum does not take ownership.
Since the original code transfers ownership and then drops the vector, if we want to keep using the vector in main, we must either clone or
borrow.
Let's adjust the code to show both approaches.
But note: the problem says "if I want to copy variable", so we focus on cloning.
However, note that cloning a vector (especially a large one) can be expensive because it requires allocating new memory and copying all
elements.
Alternatively, borrowing is often preferred when you don't need a copy.
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 3/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
We'll show:
1. Using clone to pass a copy to print_sum, so main retains ownership of the original.
2. Using a reference (borrowing) to let print_sum use the vector without taking ownership.
Let's rewrite the code for each case.
To copy a variable in Rust instead of transferring ownership, you have two main options depending on your needs:
1. Clone the Variable (Deep Copy)
Use .clone() to create a full copy of the data. This works for types that implement the Clone trait (like Vec<i32> ).
rust
fn print_sum(v: Vec<i32>) {
println!("{}", v[0] + v[1]);
// v is dropped here (but it's a clone, so the original is unaffected)
}
fn main() {
let mut v = Vec::new();
for i in 1..1000 {
v.push(i);
}
// Clone v and pass the clone to print_sum
print_sum(v.clone()); // v is cloned here
// Original v is still valid and usable
println!("Original vector length: {}", v.len());
}
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 4/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
2. Borrow Instead (No Copy)
Pass a reference ( &v ) instead of the actual vector. This avoids copying and allows the function to borrow the data temporarily.
rust
fn print_sum(v: &Vec<i32>) { // Accept a reference
println!("{}", v[0] + v[1]);
// No ownership - nothing is dropped here
}
fn main() {
let mut v = Vec::new();
for i in 1..1000 {
v.push(i);
}
// Pass a reference instead of moving ownership
print_sum(&v); // Borrow v instead of moving it
// v is still owned by main and remains usable
println!("Original vector length: {}", v.len());
}
Key Differences:
.clone() : Creates a full copy of the data (expensive for large data). The original and copy are independent.
& reference: Temporarily borrows the data without copying (zero-cost). The original data remains owned by the caller.
When to Use Which:
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 5/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
Use .clone() when you need independent copies of the data.
Use & references when you only need to read the data temporarily (most common case).
Use &mut references if you need to modify the borrowed data.
fn print_sum(a: i32, b: i32) {
println!("{}", a + b);
// the copied a and b are dropped and deallocated here
}
fn main() {
let a = 35;
let b = 42;
// copy the values and transfer
// ownership over the copies to print_sum:
print_sum(a, b);
// we still retain full control over
// the original a and b variables here
println!("We still have {} and {}", a, b);
// the original a and b are dropped and deallocated here
}
We are given a code snippet that uses i32, which is a Copy type. This means that when we pass a and b to print_sum, they are copied, so the
original variables remain valid and usable in main.
However, the user might be asking about how to copy in the context of non-Copy types (like Vec). The previous example showed that for Vec,
we need to either clone or borrow.
Let me explain the difference:
For types that implement the Copy trait (like i32, f64, bool, etc.), the assignment and function arguments will copy the value by default.
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 6/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
For types that do not implement Copy (like Vec, String, etc.), the assignment and function arguments will move the ownership by default.
So, if we want to copy a non-Copy type, we must explicitly clone it.
Example with Vec (non-Copy type):
Without clone (moves ownership, so original variable is no longer usable):
let v1 = vec![1, 2, 3];
let v2 = v1; // v1 is moved into v2, so v1 is no longer valid
With clone (creates a deep copy, so both are independent and usable):
let v1 = vec![1, 2, 3];
let v2 = v1.clone(); // v1 is still valid
In the case of the function call, if we have a non-Copy type and we want to keep using the original variable, we can either:
Option 1: Clone the entire vector and pass the clone to the function (if we want the function to take ownership of the clone).
Option 2: Pass a reference to the function (if we only want to give temporary access).
The code example provided by the user uses i32, which is Copy, so no explicit action is needed to copy.
Let me adjust the code to show both cases:
Case 1: Using Copy types (like i32) - automatic copy
Case 2: Using non-Copy types (like Vec) - must clone or borrow
We'll create two examples:
Example A: Copy type (i32)
Example B: Non-Copy type (Vec) and how to handle it.
We are also given a function print_sum that takes two i32s. We can create an analogous function for Vec that prints the sum of the first two
elements.
Since the user's original question was about copying, I'll focus on that.
Let's write:
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 7/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
This code demonstrates how copy types work in Rust. Since i32 implements the Copy trait, the values are automatically
copied when passed to the function, rather than moved.
Key Points:
1. Copy Types: Primitive types like i32 , f64 , bool , and char implement the Copy trait. When passed to functions, they are
automatically copied.
2. No Ownership Transfer: Unlike the previous example with Vec<i32> , the original variables a and b remain valid and
usable after the function call.
3. Memory Management:
The function receives copies of a and b
These copies are dropped at the end of print_sum
The original variables are dropped at the end of main
If you want to copy a non-Copy type (like Vec ):
For types that don't implement Copy (like Vec ), you need to explicitly clone them:
rust
fn print_sum(v: Vec<i32>) {
println!("{}", v[0] + v[1]);
}
fn main() {
let v = vec![35, 42];
// Explicitly clone the vector to create a copy
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 8/9
9/19/25, 9:15 AM Rust Ownership and Memory Management Explained - DeepSeek
print_sum(v.clone());
// Original v is still valid
println!("We still have {:?}", v);
}
Summary:
Copy types (primitives): Automatically copied when passed to functions
Non-Copy types (like Vec ): Must be explicitly cloned using .clone() to create a copy
References ( & ): Usually preferred over cloning for non-Copy types to avoid the cost of copying
The behavior depends on whether the type implements the Copy trait or not.
https://chat.deepseek.com/a/chat/s/a595b7c3-435c-46af-8960-3fb3c01a59ae 9/9