Reputation: 26150
I've got a very simple method that adds a node to a graph:
template<class T>
void AdjacencyList<T>::add(const GraphNode<T>& node) {
_nodes.push_back(node);
}
In another method, I iterate over the _nodes
vector, looking for the added node by address:
for (unsigned int i = 0; i < _nodes.size(); i++) {
if (&(_nodes[i]) == &node)
// do something
}
However, this does not work, because when I add node
to the _nodes
vector, the added member has a different address:
Graph::AdjacencyList<int>::add (this=0x8052338, node=...) at ../AdjacencyList.h:42
42 _nodes.push_back(node);
(gdb) p node
$1 = (const Graph::GraphNode<int> &) @0xbffff39c: {value = 123}
(gdb) n
43 }
(gdb) p _nodes[0]
$4 = (Graph::GraphNode<int> &) @0x80522b0: {value = 123}
What in the world is going on here? And more importantly, how should I be adding a member to a vector so that I can find it later?
Upvotes: 2
Views: 172
Reputation: 6829
As a rule of thumb remember that STL uses copy semantics. So unless the STL container is a collection of pointers, any element added to a STL collection will be copied.
Upvotes: 1
Reputation: 9325
If you do not want to push a copy of your object (of type T) into the container, you can use a container of smart pointers of T :
std::vector< std::shared_ptr< Graph::GraphNode<int> > > c;
std::shared_ptr< Graph::GraphNode<int> > p = std::shared_ptr< Graph::GraphNode<int> >(new Graph::GraphNode<int>(whatever));
c.push_back(c);
With this you can compare the pointer.
You can use auto_ptr, shared_ptr, unique_ptr (or boost smart pointers [2]) depending on your needs.
Boost has pointer containers as well [1].
Also, look how graph are implemented in Boost.Graph [3]. You might want to use a similar approach.
[1] http://www.boost.org/doc/libs/1_46_1/libs/ptr_container/doc/ptr_container.html
[2] http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm
[3] http://www.boost.org/doc/libs/1_46_1/libs/graph/doc/table_of_contents.html
Upvotes: 1
Reputation: 792327
Because it's a different object. All standard containers own their objects and all types that you use in standard containers must be copyable.
When you pass an object to push_back
it is copied into the vector. If you want to be able to find it later your object type must have a concept of equality where you can compare and find equivalent objects. (Either that, or you must remember which location you placed each object in the vector.)
Upvotes: 2
Reputation: 170509
The object is copied into the vector, so the address of the copy stored inside the vector is surely different from the address of the original object since no two distinct objects can have identical addresses.
To find your object later you can either compare it by some other property (one of more of its member variables) or store its index in the vector somewhere. The usual approach is that every object has some "identifier" member variable that is unique at least for all objects stored inside one vector.
Upvotes: 5