Josh Glover
Josh Glover

Reputation: 26150

Why is the address of an object added to a C++ STL vector different than its original address?

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

Answers (4)

O.C.
O.C.

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

ysdx
ysdx

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

CB Bailey
CB Bailey

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

sharptooth
sharptooth

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

Related Questions