Reputation: 27611
I have the following code:
struct Node {
id: uint
}
struct Graph {
nodes: Vec<Node>
}
impl Graph {
fn new() -> Graph {
return Graph { nodes: Vec::new() };
}
fn create_node(&mut self) -> &Node {
let index = self.nodes.len();
let node = Node { id: index };
self.nodes.push(node);
// return &node; // error: `node` does not live long enough
return &self.nodes[index]; // ...but this work fine
}
}
The idea is that the graph creates a new node and "lends" it to someone who calls the method. But I can not figure out how to return a reference to the newly created structure. The second return is working fine, but obviously not effective.
How to return a node without taking it back from the vector?
Upvotes: 0
Views: 964
Reputation: 65752
Here's why you can't return &node
:
fn create_node(&mut self) -> &Node {
let index = self.nodes.len();
let node = Node { id: index };
println!("{}", &node as *const Node);
self.nodes.push(node);
println!("{}", &self.nodes[index] as *const Node);
return &self.nodes[index];
}
Here's a sample output:
0x7fffc36a3418
0x7f4c96c2d000
As you can see, &node
and &self.nodes[index]
return completely different values. Moreover, &node
(0x7fffc36a3418) will be invalid as soon as create_node
returns, because this address points to create_node
call frame, and a call frame is freed when a function returns.
Upvotes: 2
Reputation: 127781
But I can not figure out how to return a reference to the newly created structure.
You can't. This is one of the basic errors which are ruled out by the ownership system.
Suppose you could. Then when your function returns such reference will point to destroyed memory.
You can read more on ownership in the official guide on ownership. It explains how ownership and borrowing work, including why your program is incorrect.
BTW, unless you have #[derive(Copy)]
on your Node
, taking a reference to node
won't work also because node
is moved into the vector. Ownership guide explains move semantics as well.
Upvotes: 2