Rust Ownership Quiz

Rust
0 Passed
0% acceptance

45 in-depth questions covering Rust's ownership system, move semantics, copy types, resource cleanup through Drop trait, precise drop timing, and ownership transfer patterns — with 12 code examples to solidify understanding.

45 Questions
~90 minutes
1

Question 1

What are the three rules of ownership in Rust?

A
Each value has a single owner, ownership can be transferred, values are dropped when owner goes out of scope
B
Values can have multiple owners, borrowing is automatic, garbage collection handles cleanup
C
Ownership is shared by default, references are owning, manual memory management required
D
No ownership rules, everything is reference counted
2

Question 2

What happens when you assign a String to another variable?

A
The String is copied byte-for-byte
B
Ownership is moved, the first variable becomes invalid
C
Both variables share ownership
D
A reference is created automatically
3

Question 3

Which of these types implements Copy in Rust?

A
String
B
Vec<i32>
C
i32
D
Box<i32>
4

Question 4

What is the purpose of the Drop trait?

A
To define how values are cleaned up when they go out of scope
B
To prevent values from being dropped
C
To copy values instead of moving them
D
To share ownership between multiple variables
5

Question 5

When is a value's drop method called?

A
When the variable goes out of scope
B
Only when explicitly called
C
At program termination
D
When the value is moved
6

Question 6

What happens to ownership when you pass a value to a function?

A
Ownership is transferred to the function
B
The value is automatically borrowed
C
Ownership remains with the caller
D
The value is copied
7

Question 7

How can you avoid moving ownership when passing to a function?

A
Pass a reference using &
B
Use the move keyword
C
Pass by copy
D
Use Box<T>
8

Question 8

What will this code do?

rust
fn main() {
    let s = String::from("hello");
    take_ownership(s);
    println!("{}", s); // This line
}

fn take_ownership(s: String) {
    println!("{}", s);
}
A
Print 'hello' twice
B
Compilation error on the println! line
C
Print 'hello' once
D
Runtime panic
9

Question 9

What will this code do?

rust
fn main() {
    let s = String::from("hello");
    borrow_string(&s);
    println!("{}", s); // This line
}

fn borrow_string(s: &String) {
    println!("{}", s);
}
A
Print 'hello' twice
B
Compilation error
C
Print 'hello' once
D
Runtime panic
10

Question 10

When does Rust copy values instead of moving them?

A
For all types
B
Only for types that implement Copy
C
Only for primitive types
D
Never, Rust always moves
11

Question 11

What is the difference between Copy and Clone?

A
Copy is implicit, Clone is explicit
B
Copy is for primitives, Clone is for heap data
C
They are the same
D
Copy moves, Clone copies
12

Question 12

Can you implement Copy for a struct containing a String?

A
Yes, by deriving Copy
B
No, because String doesn't implement Copy
C
Yes, but you have to implement it manually
D
Only if the String is empty
13

Question 13

What happens when a value with a custom Drop implementation goes out of scope?

A
The drop method is called automatically
B
The value is leaked
C
The value is moved to static storage
D
Compilation error
14

Question 14

In what order are drop methods called for nested scopes?

A
Inner scopes first, then outer scopes
B
Outer scopes first, then inner scopes
C
Random order
D
No guaranteed order
15

Question 15

What will this code print?

rust
struct CustomDrop {
    id: i32,
}

impl Drop for CustomDrop {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

fn main() {
    let a = CustomDrop { id: 1 };
    {
        let b = CustomDrop { id: 2 };
        let c = CustomDrop { id: 3 };
    }
    println!("End of main");
}
A
Dropping 1, Dropping 2, Dropping 3, End of main
B
Dropping 3, Dropping 2, Dropping 1, End of main
C
Dropping 1, Dropping 3, Dropping 2, End of main
D
End of main, Dropping 1, Dropping 2, Dropping 3
16

Question 16

How can you transfer ownership back from a function?

A
By returning the value
B
By using static variables
C
By modifying a global variable
D
Ownership cannot be transferred back
17

Question 17

What is ownership transfer useful for?

A
Preventing resource leaks
B
Enabling shared mutable state
C
Automatic reference counting
D
Dynamic dispatch
18

Question 18

When working with a database connection that needs to be closed when done, which ownership pattern is most appropriate?

A
Store the connection in a global variable
B
Use ownership transfer to ensure the connection is dropped when the owner goes out of scope
C
Use Rc<T> for shared ownership
D
Never close the connection
19

Question 19

What happens when you move a value into a Vec?

A
The value is copied
B
Ownership is transferred to the Vec
C
The value is borrowed
D
The Vec takes a reference
20

Question 20

How can you get ownership back from a Vec?

A
Use indexing like vec[0]
B
Use remove() or pop() methods
C
Use &vec[0]
D
Ownership cannot be retrieved from collections
21

Question 21

What will this code do?

rust
fn main() {
    let mut vec = Vec::new();
    let s = String::from("hello");
    vec.push(s);
    println!("{}", s); // This line
}
A
Print 'hello'
B
Compilation error
C
Runtime panic
D
Print nothing
22

Question 22

When implementing a cache that stores expensive-to-create objects, which ownership pattern should you use?

A
Store owned values and return them by value
B
Store references to external objects
C
Use Rc<T> for shared ownership
D
Store raw pointers
23

Question 23

What is the relationship between ownership and borrowing?

A
Borrowing temporarily suspends ownership rules
B
Borrowing creates shared ownership
C
Borrowing and ownership are unrelated
D
Borrowing replaces ownership
24

Question 24

When should you prefer moving over borrowing?

A
When you need to modify the value
B
When the caller no longer needs the value
C
When you need to return the value
D
All of the above
25

Question 25

What happens when you move a value that implements Drop?

A
Drop is called immediately
B
Drop is called when the new owner goes out of scope
C
Drop is never called
D
Drop is called twice
26

Question 26

In a web server handling requests, how should you manage database connections?

A
Create one global connection
B
Create connections per request with ownership transfer
C
Use static references
D
Never close connections
27

Question 27

What is the key difference between moving and copying?

A
Moving transfers ownership, copying duplicates data
B
Moving duplicates data, copying transfers ownership
C
They are the same
D
Moving is for primitives, copying for structs
28

Question 28

When implementing a file reader that should close the file automatically, which pattern should you use?

A
Manual close() calls
B
Ownership with Drop implementation
C
Global file handles
D
Never close files
29

Question 29

What will this code print?

rust
fn main() {
    let x = 5;
    let y = x;
    println!("x = {}, y = {}", x, y);
}
A
x = 5, y = 5
B
Compilation error
C
x = 5, y = 0
D
Runtime error
30

Question 30

What will this code do?

rust
fn main() {
    let s = String::from("hello");
    let t = s;
    println!("s = {}", s);
}
A
Print 's = hello'
B
Compilation error
C
Print 's = '
D
Runtime panic
31

Question 31

When should you implement Copy for your own types?

A
Always, for performance
B
When the type represents a simple value that should copy implicitly
C
Never, it's automatic
D
Only for primitives
32

Question 32

What happens if you try to derive Copy for a struct with a Vec field?

A
It works automatically
B
Compilation error because Vec doesn't implement Copy
C
It copies the Vec shallowly
D
It moves the Vec
33

Question 33

In a system managing temporary files, how should you handle file cleanup?

A
Manual deletion calls
B
Ownership transfer with Drop implementation for automatic cleanup
C
Store files in global state
D
Never delete temporary files
34

Question 34

What is the performance implication of moving large structs?

A
Moves are always expensive
B
Moves are cheap because they only copy pointers/metadata
C
Moves copy all data
D
Moves are impossible for large structs
35

Question 35

When implementing a parser that builds an AST, how should you handle node ownership?

A
Use Rc<T> for shared ownership
B
Transfer ownership of nodes to the AST structure
C
Store references to all nodes
D
Clone all nodes
36

Question 36

What will this code print?

rust
struct NoisyDrop {
    id: i32,
}

impl Drop for NoisyDrop {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

fn main() {
    let a = NoisyDrop { id: 1 };
    let b = a;
    println!("End of main");
}
A
Dropping 1, End of main
B
End of main, Dropping 1
C
Dropping 1, Dropping 1, End of main
D
No output
37

Question 37

When should you avoid implementing Drop?

A
When the type has no resources to clean up
B
When you want manual control over cleanup
C
When the type implements Copy
D
All of the above
38

Question 38

In a multi-threaded application, how does ownership help prevent data races?

A
By allowing shared mutable access
B
By ensuring only one thread can own mutable data
C
By using garbage collection
D
Ownership doesn't help with concurrency
39

Question 39

What happens when you return a large struct from a function?

A
The entire struct is copied to the stack
B
Ownership is transferred efficiently
C
A reference is returned
D
The function panics
40

Question 40

When implementing a smart pointer like Box<T>, how should you handle the inner value's ownership?

A
Store it as a reference
B
Take ownership in the constructor and return it in Drop
C
Use Rc<T> internally
D
Never take ownership
41

Question 41

What is the relationship between ownership and the borrow checker?

A
The borrow checker enforces ownership rules
B
Ownership rules are separate from borrowing
C
The borrow checker replaces ownership
D
Ownership is checked at runtime
42

Question 42

In a library providing an API, how should you design function signatures for ownership?

A
Always take ownership
B
Always borrow
C
Use ownership when the function consumes the value, borrowing when it observes
D
Use Rc<T> for everything
43

Question 43

What will this code do?

rust
fn main() {
    let mut vec = Vec::new();
    for i in 0..3 {
        let s = format!("item {}", i);
        vec.push(s);
    }
    println!("Vec has {} items", vec.len());
    // vec goes out of scope here
}
A
Print 'Vec has 3 items' and leak memory
B
Compilation error
C
Print 'Vec has 3 items' and clean up properly
D
Runtime panic
44

Question 44

When implementing a configuration struct that holds database URLs, which ownership pattern is most appropriate?

A
Store String values for owned URLs
B
Store &str references
C
Use Rc<String> for sharing
D
Store raw pointers
45

Question 45

What is the most important benefit of Rust's ownership system?

A
Faster compilation
B
Memory safety without garbage collection
C
Object-oriented programming
D
Dynamic typing

QUIZZES IN Rust