Почему адрес объекта, добавляемого в вектор CL STL, отличается от его исходного адреса? - PullRequest
2 голосов
/ 19 апреля 2011

У меня есть очень простой метод, который добавляет узел к графику:

  template<class T>
  void AdjacencyList<T>::add(const GraphNode<T>& node) {
    _nodes.push_back(node);
  }

В другом методе я перебираю вектор _nodes, ища добавленный узел по адресу:

for (unsigned int i = 0; i < _nodes.size(); i++) {
  if (&(_nodes[i]) == &node)
    // do something
}

Однако это не работает, потому что, когда я добавляю node к вектору _nodes, добавленный член имеет другой адрес:

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}

Что в мирездесь происходит?И что еще более важно, как мне добавить члена в вектор, чтобы я мог найти его позже?

Ответы [ 4 ]

5 голосов
/ 19 апреля 2011

Объект скопирован в вектор, поэтому адрес копии, хранящейся внутри вектора, безусловно, отличается от адреса исходного объекта, поскольку никакие два разных объекта не могут иметь одинаковые адреса.

Чтобы найти ваш объект позже, вы можете либо сравнить его по какому-либо другому свойству (одной из нескольких переменных-членов), либо сохранить где-нибудь его индекс в векторе. Обычный подход заключается в том, что каждый объект имеет некоторую переменную-член «идентификатор», которая уникальна, по крайней мере, для всех объектов, хранящихся в одном векторе.

2 голосов
/ 19 апреля 2011

Потому что это другой объект. Все стандартные контейнеры владеют своими объектами, и все типы, которые вы используете в стандартных контейнерах, должны быть копируемыми.

Когда вы передаете объект в push_back, он копируется в вектор. Если вы хотите найти его позже, ваш тип объекта должен иметь концепцию равенства, где вы можете сравнивать и находить эквивалентные объекты. (Либо так, либо вы должны помнить, в каком месте вы разместили каждый объект в векторе.)

1 голос
/ 19 апреля 2011

Как правило, помните, что STL использует семантику копирования. Таким образом, если контейнер STL не является коллекцией указателей, любой элемент, добавленный в коллекцию STL, будет скопирован .

1 голос
/ 19 апреля 2011

Если вы не хотите помещать копию вашего объекта (типа T) в контейнер, вы можете использовать контейнер интеллектуальных указателей 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);

С этим вы можете сравнитьуказатель.

Вы можете использовать auto_ptr, shared_ptr, unique_ptr (или повысить умные указатели [2]) в зависимости от ваших потребностей.

В Boost также есть контейнеры указателей [1].

Также посмотрите, как граф реализован в Boost.Graph [3].Возможно, вы захотите использовать аналогичный подход.

[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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...