Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
Conan
0 / 0 / 0
Регистрация: 05.12.2014
Сообщений: 10
1

Теряю ссылку на элемент в std::vector после того, как делаю push_back следующего элемента

05.12.2014, 19:16. Просмотров 609. Ответов 6
Метки нет (Все метки)

Добрый день!

Подскажите пожалуйста в чем причина моей ошибки. Сам работал на чистом C++, то есть использовал все по минимуму из C++. В основном структуры, оператор new, классы, всегда сам чистил память, ну не обходилось без велосипедов, но всегда работа шла. Тут решил сделать проект на STL, думал что будет быстрее спроектировать и затем нужные участки переписать на C-way. Но не тут то было...

В общем я анализирую XML файл, в котором есть "множества", которые могут принадлежать "владельцам", а могут и нет.
Все множества я складываю в vector<Set>, и если множество используется "владельцем" - я в поле "владелец"->"*множество" указываю указатель на элемент в vector<Set>.

Пример XML
XML
1
2
3
4
5
6
7
8
9
10
11
<owner name="Ivan">
  <set>
  <!-- данные -->
  </set>
</owner>
<owner name="Semen" ref="CoolSet" />
<owner name="Vova" ref="CoolSet" />
 
<set name="CoolSet">
<!-- данные -->
</set>
Set может быть личный, тогда он описывается внутри тега owner, но может быть общий. Поэтому моя идея заключалась, чтобы все Set добавить в vector, а на нужные кинуть ссылки "владельцам".

ПРОБЛЕМАТИКА
Когда добавляю в vector первый Set, беру ссылку как &vector.back() и и отдаю ее в owner.set. Все работает.
Но когда я добавляю второй Set в vector все ломается. owner.set уже не указывает на первый элемент, он указывает на что-то непонятное, причем второе поле vector<int> symbols имеет размерность 4096, иногда даже больше.

Может я чего не понимаю, как работают коллекции в C++. До этого в подобными библиотеками работал только в Java, но такое делать со ссылками и там не приходилось. Помогите кто-чем может ) плиз

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "stdafx.h"
 
struct Set {
    std::string     name;
    vector<int>     symbols;
};
 
typedef vector<Set> Sets;
 
struct Owner {
    std::string name;
    Set *set;
};
 
//+------------------------------------------------------------------+
//| Program entry point                                             |
//+------------------------------------------------------------------+
int main(int argc, TCHAR* argv[]) {
    Sets list;
 
    Set *a = new Set();
    Set *b = new Set();
    
    a->name = "A";
    b->name = "B";
 
    list.push_back(*a);
 
    Owner *ow = new Owner();
    ow->name = "ivan";
 
    ow->set  = &list.back();
    ow->set->name = "cool";
    // все по прежнему работает
 
    // эта операция все ломает. ERROR тут
    list.push_back(*b);
    // после этого ow->set уже не указывает на 1й элемент лист  и ow->set->name не равно cool
}
Внизу приложил два скрина отладчика. Первый до точки останова на
C++
1
list.push_back(*b);
второй уже после.
0
Миниатюры
Теряю ссылку на элемент в std::vector после того, как делаю push_back следующего элемента   Теряю ссылку на элемент в std::vector после того, как делаю push_back следующего элемента  
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.12.2014, 19:16
Ответы с готовыми решениями:

Std::vector push_back vs emplace_back
Бывают ли случаи, когда push_back невозможно реализовать через emplace_back,...

std::vector<T>.push_back(T) - Error
Не пойму в чем дело, но при добавлении (CTextureManager :: load(const char*...

Как передать целочисленную матрицу типа std::vector<std::vector<int> > в функцию?
Здравствуйте. Почитал на форуме, но так и не понял что я делаю не так....

На основе исходного std::vector<std::string> содержащего числа, создать std::vector<int> с этими же числами
подскажите есть вот такая задача. Есть список . Создать второй список, в...

Передача функции указатель на элемент std::vector<std::string>
Доброй ночи тем, кому не спится (или живет в другом часовом поясе:p)! Есть...

6
DrOffset
8919 / 4800 / 1176
Регистрация: 30.01.2014
Сообщений: 7,834
05.12.2014, 19:24 2
Цитата Сообщение от Conan Посмотреть сообщение
Но когда я добавляю второй Set в vector все ломается. owner.set уже не указывает на первый элемент, он указывает на что-то непонятное
Так и должно быть. Указатели (и ссылки) на элементы инвалидируются при следующем добавлении, т.к. вектору для того, чтобы сделать это, потребуется реаллокация. Реаллокация нужна, чтобы обеспечить требование непрерывности данных в векторе (как в обычном массиве). Если нужно чтобы добавление не влияло на остальные элементы, нужно использовать другую структуру данных, например list. Или сохранять индекс элемента, вместо ссылки на него.
1
Conan
0 / 0 / 0
Регистрация: 05.12.2014
Сообщений: 10
05.12.2014, 19:32  [ТС] 3
Я думаю, что проблема состоит в том, что capacity vectora = 1, то есть при добавлении нового элемента выделяется новая память и все элементы копируются туда. Тогда указатель, который указывает на старое расположение ссылается на всякую ерунду.

Добавлено через 1 минуту
Спасибо, тоже уже начал догадываться.
0
DrOffset
8919 / 4800 / 1176
Регистрация: 30.01.2014
Сообщений: 7,834
05.12.2014, 19:37 4
Цитата Сообщение от Conan Посмотреть сообщение
Я думаю, что проблема состоит в том, что capacity vectora = 1, то есть при добавлении нового элемента выделяется новая память и все элементы копируются туда. Тогда указатель, который указывает на старое расположение ссылается на всякую ерунду.
Да, верно.

Можно конечно, зарезервировать нужное количество памяти через метод reserve и это на некоторое время обезопасит от перевыделения. Но в долгосрочной перспективе это сомнительное решение.
В данном случае, мне кажется, это прямой намек со стороны задачи, что необходимо сменить структуру данных на более подходящую
1
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7078 / 3382 / 458
Регистрация: 04.12.2011
Сообщений: 9,405
Записей в блоге: 5
05.12.2014, 19:41 5
Del, не успел
1
Conan
0 / 0 / 0
Регистрация: 05.12.2014
Сообщений: 10
05.12.2014, 19:48  [ТС] 6
Спасибо большое, за помощь и быстрые ответы!
Убедился, что в правильном направлении мыслю.
По поводу того, чтобы использовать std::list или индекса массива, thanks!
Я привык использовать массивы и сам выделать память и реаллокацию сам делать, видимо меня это и подвело. Взял для простоты vector, а про реаллокацию забыл. Наука будет.

Я так-то привык все один разбираться, редко за помощью обращаюсь, но тут не выдержал уже. Вместо того, чтобы продолжать "дебажить код" и "ставить эксперименты", расписал все тут и вроде даже сам разобрался пока писал )))
0
DrOffset
05.12.2014, 20:12     Теряю ссылку на элемент в std::vector после того, как делаю push_back следующего элемента
  #7

Не по теме:

Цитата Сообщение от Conan Посмотреть сообщение
расписал все тут и вроде даже сам разобрался пока писал )))
Это всегда помогает :)

0
05.12.2014, 20:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.12.2014, 20:12
Привет! Вот еще темы с ответами:

Как удалить первые три элемента в std::vector?
Добрый вечер! у меня есть вектор vector&lt;MyClass&gt; v; где MyClass - какой-либо...

Как изменять размер std::vector<std::vector>?
Здравствуйте, как нужно изменять размер std::vector&lt;std::vector&gt; например: ...

Удаление элемента из std::vector<>
- Здравствуйте завсегдатаи! Подскажите пожалуйста, можно ли из STL-ского...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru