Несколько вещей.
Прежде всего, насколько я могу судить NNodes
просто отслеживает размер. Но для этого у вас есть std::vector::size()
. Затем вы используете его, чтобы получить последний вставленный элемент, но вы можете просто использовать std::vector::back()
для этого: return &N.back();
.
Также ваш параметр передается по значению, когда он, вероятно, должен быть передан посредством const-reference: const string& h
. Это позволяет избежать ненужных копий, и вообще * вы должны передавать вещи с помощью ссылки на const, а не по значению.
И это плохо:
node n;
N.push_back(n);
N[NNodes].setname(h);
node
, вероятно, следует иметь конструктор, который принимает const string&
и устанавливает имя во время инициализации. Таким образом, вы никогда не может иметь узел без имени, например:
node n(h);
N.push_back(n);
Или более лаконична:
N.push_back(node(h));
Намного лучше.
Во-вторых, да, vector
может аннулировать указатели на элементы; а именно, когда необходимо увеличить пропускную способность вектора. Если вы можете, reserve()
вместимость вверх, чтобы избежать перераспределения. В вашем случае вы не можете, так что вы можете пройти два разных маршрута.
Первый маршрут: a level of indirection. Вместо того, чтобы прямо указывать на вещи, введите их индекс в массив. Обратите внимание, что, хотя их адрес может измениться, их местоположение внутри вектора не будет. У вас было бы Simulator::FindNode
возвращение size_t
и возврат N.size() - 1
. Добавьте участника, как node& GetNode(size_t index)
, который просто делает return N[index];
(будет проверка ошибок, если вы пожелаете). Теперь, когда вам нужен член, передайте индекс этому члену GetNode
, и вы получите ссылку на этот узел назад.
Другой маршрут - изменить ваш контейнер. Например, вы можете использовать deque
. Это не имеет непрерывного хранения, но это очень похоже на vector
. push_back
и pop_back
все еще O (1), и он по-прежнему обладает хорошей кэш-связностью. (И, кстати, deque
торгует смежное хранение способности к push_front
и pop_front
в O (1) время, а)
Важно то, что deque
будет не ТЕРЯЮТСЯ указатели во время толчка или попа-операции из любых конец.Он работает с гибридом векторных списков, где вы получаете куски хранения для связанных друг с другом элементов. Измените основное хранилище на deque
(и не принимайте и не помещайте что-либо посередине), и вы можете указать на все просто.
Однако, из того, что я могу сказать, у вас ужасно неэффективная карта. Вы сопоставляете имена с узлами. Вероятно, вы должны просто использовать std::map
, который имеет точный интерфейс, который вы пытаетесь воссоздать. Вы даже можете указать на любой элемент на карте, который никогда не делает ничего недействительным.
* Правило, проходят по константной-ссылки, если тип не является примитивной (встроенный как int
, double
и т.д.), если размер типа меньше sizeof(void*)
, или если вы будете нуждаться его копия в любом случае.
То есть, не делайте этого:
void foo(const std::string& s)
{
std::string ss(s); // make a copy, use copy
}
Но сделать это:
void foo(std::string s) // make a copy, use copy
{
}
Я отформатирован ваш пост. Я также изменил ваш код, * пожалуйста * помещайте пробелы между вещами. Do: 'for (i = 0; i> NodeName;' вместо 'inp_file >> NodeName;' , это гораздо более читаемо. –
GManNickG
Я хотел бы предложить вам отметить ответ GMan как Accepted. Здесь он самый полный. –
Спасибо всем, кто ответил особенно GMan и Steven Sudit, теперь у меня слишком много, чтобы учиться и модифицировать. – Ahmed