Форум программистов, компьютерный форум CyberForum.ru

Проблема с указателем на элемент вектора - C++

Восстановить пароль Регистрация
 
 
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
15.07.2015, 16:38     Проблема с указателем на элемент вектора #1
Всем доброго времени суток. Не могу никак выкрутиться)
Допустим, у нас есть класс "А" с параметрами:
C++
1
    std::vector <TNode*> nodes;
И есть зависимый от него класс "В" с параметрами:
C++
1
    TNode* firstNode;
В классе "В" сохранен указатель на элемент класса "А". Но элементы можно удалять независимо друг от друга. При удалении объекта класса "В" нет никаких проблем. Но при удалении объекта класса "А" (delete по вектору) указатель в классе "В" невозможно разыменовать и прога падает.
TNode:
C++
1
    int getBaseY(){return *this->baseY;}
Как быть, чет не приходят идеи в голову
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
smartpointer
 Аватар для smartpointer
64 / 58 / 23
Регистрация: 17.02.2014
Сообщений: 250
15.07.2015, 18:19     Проблема с указателем на элемент вектора #2
Если элемент общий для двух классов - значит он указывает на один адрес, неудивительно что вы получаете падение программы - класс A удалил свои данные, но класс B продолжает ссылаться на них - разыменование приводит к падению поскольку по адресу уже ничего нету или записаны другие данные. Вообще хотелось бы увидеть весь код, может дело в другом.
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
15.07.2015, 18:29  [ТС]     Проблема с указателем на элемент вектора #3
smartpointer, я прекрасно понимаю из-за чего падает. Мне нужны идеи как избежать краха программы. Как проверить этот указатель, возможно ли разыменование для него или нет ? как отловить момент удаления из класса "В"

Добавлено через 5 минут
Хотя нет, все гораздо веселее >_<
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class TNode{
    public:
        TNode(int* X, int* Y);
        void changeXY(int dX, int dY);
        //
        int getHX(){ return *this->baseX+this->dX;}
        int getHY(){ return *this->baseY;}
 
        int getVX(){ return *this->baseX;}
        int getVY(){ return *this->baseY+ this->dY;}
        //
        int getBaseX(){return *this->baseX;}
        int getBaseY(){return *this->baseY;}
    private:
        unsigned int noNode;    //номер узла
 
        int* baseX;             //координаты базового узла
        int* baseY;
        int dX,dY;              //координаты узла
};
Происходит постоянная отрисовка объекта. После удаления объекта от А, происходит затык в В.
smartpointer
 Аватар для smartpointer
64 / 58 / 23
Регистрация: 17.02.2014
Сообщений: 250
15.07.2015, 18:29     Проблема с указателем на элемент вектора #4
Нужна ссылка на указатель, но если не ошибаюсь std::vector этого не позволяет делать - вместо этого попробуйте хранить адрес самого указателя (std::vector<TNode**>) и при удалении элемента нулите указатель, чтобы класс B не мог его удалить - соответсвенно в классе B нужно проверять этот указатель на ноль, как-то так.
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
15.07.2015, 18:34     Проблема с указателем на элемент вектора #5
Лучше хранить индекс элемента из вектора, а не указатели.
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
15.07.2015, 18:44  [ТС]     Проблема с указателем на элемент вектора #6
smartpointer, при удалении А пишу nodes[i] = NULL; но при проверке в В он не является нулевым. Как это сделать правильно ? DrOffset, изначально исходный вектор недоступен в классе В
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
15.07.2015, 18:49     Проблема с указателем на элемент вектора #7
Цитата Сообщение от Fobes Посмотреть сообщение
изначально исходный вектор недоступен в классе В
Это непреодолимое условие?

Как-то вот так сделать не вариант?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class TNode{
    public:
        TNode(int X, int Y);
        void changeXY(int dX, int dY);
        //
        int getHX(std::vector<int> & v){ return v[baseX] + dX;}
        int getHY(std::vector<int> & v){ return v[baseY];}
 
        int getVX(std::vector<int> & v){ return v[baseX];}
        int getVY(std::vector<int> & v){ return v[baseY]+ dY;}
        //
        int getBaseX(std::vector<int> & v){return v[baseX];}
        int getBaseY(std::vector<int> & v){return v[baseY];}
    private:
        unsigned int noNode;    //номер узла
 
        int baseX;             //координаты базового узла
        int baseY;
        int dX,dY;              //координаты узла
};
Ну и присыпать необходимыми проверками, где нужно.
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
15.07.2015, 19:03  [ТС]     Проблема с указателем на элемент вектора #8
DrOffset, в общем сейчас все сделано так: пишу графический редактор, есть элементы, которые между собой соединяются проводом. Каждый элемент несет в себе узлы (TNode) к которым можно цеплять провод, координаты которых меняются с перемещением базового объекта. Кликаем по двум элементам, создается объект провода между ними в который передаются указатели на ТNode двух объектов. И все двигается с закрепленными в нужных местах проводами. Методы которые вы сиправили используются только для отрисовки. Нужно много править чтобы оттуда передавать вектора.
smartpointer
 Аватар для smartpointer
64 / 58 / 23
Регистрация: 17.02.2014
Сообщений: 250
15.07.2015, 19:06     Проблема с указателем на элемент вектора #9
Вот накидал пример (вроде не крашится), однако вам придется управлять как-то вектором, если вы будете удалять узел из B объекта.
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <vector>
 
struct Node
{
    int a;
    Node(const int& val): a(val){}
    ~Node()
    {
        std::cout<<"Node is destroyed"<<std::endl;
    }
};
 
class A
{
    std::vector<Node**> nodes;
public:
    void Add(Node** node)
    {
        nodes.push_back(node);
    }
    void Delete()
    {
        if(nodes.size())
        {
            Node** temp = nodes[nodes.size()-1];
            if(*temp)
            {
                nodes.pop_back();
                delete *temp;
                *temp = 0;
            }
        }
    }
};
class B
{
    Node* node;
public:
    B()
    {
       node = new Node(10);
    }
    ~B()
    {
        if(node)
        {
            delete node;
            node = 0;
        }
    }
    inline Node** GetNode()
    {
        return &node;
    }
};
 
int main()
{
    A a;
    B array[10];
    for(unsigned i = 0; i < 10; i++)
        a.Add(array[i].GetNode());
    //уничтожаем два узла из A
    std::cout<<"A destruction"<<std::endl;
    a.Delete();
    a.Delete();
    std::cout<<"B destruction"<<std::endl;
    return 0;
}
Fallenworld
75 / 75 / 9
Регистрация: 14.04.2014
Сообщений: 408
15.07.2015, 19:12     Проблема с указателем на элемент вектора #10
никнейм первого ответившего какбэ намекает на самое просто и мощное решение. Но я слышал, что умные указатели в векторе лучше не хранить.
А вообще я не совсем понял проблему.
C++
1
2
3
4
5
vector<TNode*> nodes;
TNode *first = new TNode;
nodes.push_back(first);
delete first;
for(TNode* node: nodes) delete node;
и на последней строке падает, так?
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
15.07.2015, 19:23     Проблема с указателем на элемент вектора #11
Fobes, тогда уж проще в векторе держать shared_ptr вместо объектов, а в узлах weak_ptr.
http://ru.cppreference.com/w/cpp/memory/shared_ptr
http://ru.cppreference.com/w/cpp/memory/weak_ptr

https://msdn.microsoft.com/en-us/library/hh279672.aspx
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
15.07.2015, 19:32  [ТС]     Проблема с указателем на элемент вектора #12
DrOffset, пишу в embarcadero xe8, как я понял там таких умных указателей нету =/
Fallenworld, я вроде достаточно понятно все расписал
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6172 / 2901 / 284
Регистрация: 04.12.2011
Сообщений: 7,722
Записей в блоге: 3
15.07.2015, 19:46     Проблема с указателем на элемент вектора #13
Цитата Сообщение от Fobes Посмотреть сообщение
при удалении А пишу nodes[i] = NULL; но при проверке в В он не является нулевым
Fobes, он это кто? В векторе хранятся указатели и в другом классе хранятся указатели и общее у них - адреса на которые они смотрят. Но это же разные переменные. Вспомните, - при создании вектора он запускает конструктора, то есть создаёт объекты. Поэтому установив в ноль его указатель Вы ничего не сделали для изменения указателя в классе B так как это просто разные переменные. А память то освободили и разыменование по адресу - UB. Как вариант, совет smartpointer, может сработать. Имея указатель на указатель в векторе и указатель в классе B вы будете иметь доступ к одной и той же переменной из обоих классов. Однако такое построение это надругательство над инкапсуляцией как таковой.
Если связь этих классов неминуема, то может сделать один вложенным и организовать доступ к указателю через класс член (его метод)? То есть в векторе хранить не непосредственно указатели, а экземпляры B (которые хранят указатели).
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
15.07.2015, 20:09     Проблема с указателем на элемент вектора #14
Цитата Сообщение от Fobes Посмотреть сообщение
DrOffset, пишу в embarcadero xe8, как я понял там таких умных указателей нету =/
Такие же есть в бусте. В embarcadero, насколько я помню, он штатным установщиком даже ставится вместе со всем остальным.
http://www.boost.org/doc/libs/1_58_0...shared_ptr.htm
http://www.boost.org/doc/libs/1_58_0...r/weak_ptr.htm
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
15.07.2015, 23:53  [ТС]     Проблема с указателем на элемент вектора #15
DrOffset, так, доставил в свою версию буст)) А можно чуть поразвернутее про выбор именно этих умных указателе ?
Avazart
 Аватар для Avazart
6905 / 5145 / 253
Регистрация: 10.12.2010
Сообщений: 22,630
Записей в блоге: 17
16.07.2015, 00:09     Проблема с указателем на элемент вектора #16
Цитата Сообщение от DrOffset Посмотреть сообщение
Лучше хранить индекс элемента из вектора, а не указатели.
И чем это поможет?
Абсолютно ничем, получите невалидный индекс вместо невалидного указателя.

Добавлено через 1 минуту
Умные же указатели- тоже не подходят так как не решат проблему согласования, ибо просто не удалят элемент.
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 207
16.07.2015, 00:10  [ТС]     Проблема с указателем на элемент вектора #17
Avazart, как же быть то тогда ?
Avazart
 Аватар для Avazart
6905 / 5145 / 253
Регистрация: 10.12.2010
Сообщений: 22,630
Записей в блоге: 17
16.07.2015, 00:23     Проблема с указателем на элемент вектора #18
Цитата Сообщение от Fobes Посмотреть сообщение
как отловить момент удаления из класса "В"
Класс B должен "извещать" из своего деструктора все зависимые классы об своем удалении.

Есть другой вариант не удалять объект вообще а просто помечать его "невалидным" и действовать как будто его нет, самое просто, но ценой памяти.
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
16.07.2015, 00:26     Проблема с указателем на элемент вектора #19
Цитата Сообщение от Avazart Посмотреть сообщение
И чем это поможет?
Невалидный индекс хотя бы можно проверить. Битый указатель же не проверишь уже точно.
Цитата Сообщение от Avazart Посмотреть сообщение
Умные же указатели- тоже не подходят так как не решат проблему согласования, ибо просто не удалят элемент.
Вообще все эти советы были даны исходя из того, что автор хочет отделаться малой кровью. Не переписывать код. Естественно, правильным подходом было перепроектировать и переписать код полностью. В том числе с учетом твоих замечаний по поводу извещения об удалении, с которыми я полностью согласен.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.07.2015, 00:28     Проблема с указателем на элемент вектора
Еще ссылки по теме:

В чем разница между указателем и указателем на указатель? C++
C++ Проблема с указателем на функцию

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

Или воспользуйтесь поиском по форуму:
Avazart
 Аватар для Avazart
6905 / 5145 / 253
Регистрация: 10.12.2010
Сообщений: 22,630
Записей в блоге: 17
16.07.2015, 00:28     Проблема с указателем на элемент вектора #20
Цитата Сообщение от DrOffset Посмотреть сообщение
Невалидный индекс хотя бы можно проверить.
Мм и каким чудом?
Куда будет указывать индекс после удаления? На другой элемент?
Yandex
Объявления
16.07.2015, 00:28     Проблема с указателем на элемент вектора
Ответ Создать тему
Опции темы

Текущее время: 15:13. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru