Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 212
#1

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

15.07.2015, 16:38. Просмотров 1059. Ответов 54
Метки нет (Все метки)

Всем доброго времени суток. Не могу никак выкрутиться)
Допустим, у нас есть класс "А" с параметрами:
C++
1
    std::vector <TNode*> nodes;
И есть зависимый от него класс "В" с параметрами:
C++
1
    TNode* firstNode;
В классе "В" сохранен указатель на элемент класса "А". Но элементы можно удалять независимо друг от друга. При удалении объекта класса "В" нет никаких проблем. Но при удалении объекта класса "А" (delete по вектору) указатель в классе "В" невозможно разыменовать и прога падает.
TNode:
C++
1
    int getBaseY(){return *this->baseY;}
Как быть, чет не приходят идеи в голову
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.07.2015, 16:38
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Проблема с указателем на элемент вектора (C++):

Проблема с указателем на функцию - C++
Доброго времени суток, пишу приложение, которое реализует все функции АТД (двусвязный список). Есть стандартная библиотека, есть функция...

Проблема с указателем на строку - C++
Пишу класс Строка на Visual Studio. Проблема с функцией-оператором + ( Он у меня только на добавление символа, так как мне большего на...

Список с указателем на последний элемент - C++
Приветствую. Есть циклический односвязный список с зацикливанием через голову. Требуется: убрать зацикливание через голову, а...

Определить количество положительных элементов вектора С(10) и заменить этим значением минимальный элемент вектора А(5) - C++
Ребята помогите пожалуйста с задачкой. Я сам не шарю в C++, но в этом семестре появился этот предмет! И завтра его надо будет сдать :( Буду...

В чем разница между указателем и указателем на указатель? - C++
int x, *p, *q; x=10; p=&amp;x; q=p; cout&lt;&lt;*q; int x, *p, **q; x=10; p=&amp;x; q=&amp;p;

Изменение вектора. Наибольший элемент вектора - C++
Добрый день, нужна оценка кода. Пропустил занятия, делал по теории, опирался на массивы. Скажите, правильно ли реализовано? Создать...

54
DrOffset
7506 / 4502 / 1023
Регистрация: 30.01.2014
Сообщений: 7,362
16.07.2015, 11:02 #31
Fobes, И да, вариант с умными указателями (выше пост) будет работать. Он хуже, чем некоторые другие варианты, требующие изменения архитектуры, но работать он будет.

Добавлено через 1 минуту
Цитата Сообщение от Fobes Посмотреть сообщение
Мы передаем нужный нам указатель в В и там храним в виде firstNode, lastNode
Ну если я все верно понял, то тогда у тебя вроде бы правильно (кроме попытки освободить два указателя за раз).
0
Fobes
16 / 16 / 2
Регистрация: 19.09.2012
Сообщений: 212
16.07.2015, 11:04  [ТС] #32
DrOffset, окай, с удалением учту, всем спасибо большое. Вопрос решен. ^_^
0
Avazart
Эксперт С++
7420 / 5510 / 316
Регистрация: 10.12.2010
Сообщений: 24,597
Записей в блоге: 17
16.07.2015, 14:15 #33
Если наброском как-то так:
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
class I
{
     public:
        virtual ~I(){};
        virtual void bDeleted(class B* b)= 0;
};
 
class B
{
    public:
        B():x_(0),y_(0){}
        virtual ~B()
        {
            for(size_t i=0; i<dependences_.size(); ++i)
             dependences_[i]->bDeleted(this);
        }
 
        void appendI(I* obj)
        {
            dependences_.push_back(obj);
        }
 
        void eraseI(I* obj)
        {
                std::vector<I*>::iterator it=
                    std::find(dependences_.begin(),dependences_.end(),obj);
                if(it!=dependences_.end())
                    dependences_.erase(it);
        }
 
        void setPos(int x,int y){ x_= x; y_= y; }
        int x()const{ return x_; }
        int y()const{ return y_; }
    private:
        int x_,y_;
        std::vector<I*> dependences_;
};
 
 
class A: public I
{
    public:
     A():I(){}
 
     virtual ~A()
     {
         for(size_t i=0; i<bb_.size(); ++i)
             bb_[i]->eraseI(this);
     }
 
     virtual void bDeleted(B* b)
     {
            eraseB(b);
     }
 
     void appendB(B* b)
     {
         bb_.push_back(b);
         b->appendI(this);
     }
 
     void eraseB(B* b)
     {
            std::vector<B*>::iterator i=
                std::find(bb_.begin(),bb_.end(),b);
            if(i!=bb_.end())
                bb_.erase(i);
     }
 
     const std::vector<B*>& bb()const
     {
         return bb_;
     }
 
    private:
     std::vector<B*> bb_;
};
 
 
class C: public I
{
    public:
     C():I(),b_(0){}
     virtual ~C()
     {
            if(b_) b_->eraseI(this);
     }
 
     virtual void bDeleted(B* b)
     {
            b_= 0;
     };
 
     const B* b()const
     {
         return b_;
     }
 
     void setB(B* b)
     {
         b_= b;
         b->appendI(this);
     }
 
    private:
        B* b_;
};
 
int main()
{
 
         B* b= new B;
         b->setPos(10,20);
 
         A* a= new A;
         a->appendB(b);
 
         C* c= new C;
         c->setB(b);
 
         delete b;
 
         std::cout<< a->bb().size() << std::endl;
 
         if(c->b()!=0) // b is valid pointer?
            std::cout<< c->b()->x()<<":"<< c->b()->y()<<std::endl;
         else
            std::cout<<"b deleted!"<<std::endl;
 
 
         delete a;
         delete c;
 
    getchar();
    return 0;
}
1
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6911 / 3188 / 315
Регистрация: 04.12.2011
Сообщений: 8,825
Записей в блоге: 5
16.07.2015, 14:31 #34
Цитата Сообщение от DrOffset Посмотреть сообщение
Только вот есть два момента. Если мы удаляем из вектора, например из середины, то адреса следующих за удаленным объектов изменятся.
В векторе же указатели TNode*. Их адреса не используются. А адреса которые в них хранятся не изменяются. Хуже другое. Если в классе хранится булева переменная вроде is_valid, то где она будет когда память из под объекта освободится. Во многих тестах там где и была, но разве это путь к победе?
Тут надо указатель оборачивать чем-то, но тогда уж лучше смарт использовать какой-то.
Или сделать один класс полем другого и обращаться по указателю только через владельца. В идеале вообще не давать указатель наружу.
0
DrOffset
7506 / 4502 / 1023
Регистрация: 30.01.2014
Сообщений: 7,362
16.07.2015, 16:03 #35
Цитата Сообщение от IGPIGP Посмотреть сообщение
Хуже другое. Если в классе хранится булева переменная вроде is_valid, то где она будет когда память из под объекта освободится.
Возможно у автора ошибки в его коде. Но я без полной картины не могу сделать точных выводов. Да и не особо хочется. Неблагодарное это занятие, как правило

Цитата Сообщение от IGPIGP Посмотреть сообщение
В векторе же указатели TNode*.
Да вот фиг его знает. Он ссылается из Node на какие-то инты. А где эти инты лежат, мне сперва было не понятно. Вот я и подумал, что в векторе другом
0
Avazart
Эксперт С++
7420 / 5510 / 316
Регистрация: 10.12.2010
Сообщений: 24,597
Записей в блоге: 17
16.07.2015, 16:16 #36
Цитата Сообщение от DrOffset Посмотреть сообщение
C++
1
if(boost::shared_ptr<int> spt = ref.lock())/*   "=" ?? */
Опечатка или Си-стайЛ?
0
DrOffset
7506 / 4502 / 1023
Регистрация: 30.01.2014
Сообщений: 7,362
16.07.2015, 16:23 #37
Цитата Сообщение от Avazart Посмотреть сообщение
Опечатка или Си-стайЛ?
Нет, тут как раз все правильно. Причем такое писать можно только в С++ (объявление переменных в условии if).
В этом выражении после конструирования переменной spt, у нее будет вызван operator bool(), ну и соответственно произведена проверка.
0
Avazart
16.07.2015, 16:26
  #38

Не по теме:

Значит стайл ...

C
1
2
3
4
5
6
FILE *fp;
if((fp=fopen("test", "rb+"))==NULL) 
{
  printf("He удается открыть файл.\n");
  exit(1);
}

0
DrOffset
7506 / 4502 / 1023
Регистрация: 30.01.2014
Сообщений: 7,362
16.07.2015, 16:34 #39

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Значит Си стайл ...
Поясни?


Добавлено через 7 минут

Не по теме:

Avazart, ты путаешь. Мой код и твой - разные. Тут где-то на форуме проскакивал вопрос из книги Страуструпа с таким же кодом. Суть этого в том, чтобы объявлять переменные там, где они используются и сразу инициализировать их. В данном случае spt имеет смысл только внутри if и его область видимости ограничена скобками if. Это чисто С++сный подход. В этом случае = - это не присваивание, а инициализация. Т.е. здесь работает конструктор. Поэтому этот код не вызовет у компилятора никаких предупреждений.

0
Avazart
16.07.2015, 16:34
  #40

Не по теме:

Че не понятно... плохая практика в условиях использовать присваивание, плохо читается = / == .

0
DrOffset
16.07.2015, 16:41
  #41

Не по теме:

Avazart, это не присваивание.

Добавлено через 1 минуту

Цитата Сообщение от Avazart Посмотреть сообщение
if(boost::shared_ptr<int> spt = ref.lock())/* "=" ?? */
Аналог:
C++
1
if(boost::shared_ptr<int> spt(ref.lock()))

0
Avazart
16.07.2015, 16:50
  #42

Не по теме:

Мм и не смущает конструирование в if ? Как по мне, как минимум непривычно.
Я бы скорее использовал expired().

0
DrOffset
16.07.2015, 16:57
  #43

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Мм и не смущает конструирование в if ? Как по мне, как минимум непривычно.
"Это так и задумано" (с). Цель этого намеренно сузить область видимости переменной, дабы исключить ее случайное применение. Очевидно, что нулевой пойтер нельзя разыменовывать, поэтому нет смысла оставлять видимость переменной после условия. Когда такое происходит в for, то вопросов же не возникает:
C++
1
2
3
4
for(int i = 0; i < 10; ++i)
//vs
int i;
for(i = 0; i < 10; ++i)
Как раз таки второе - это сишный подход. А первое - С++. В if тоже самое.

0
Avazart
16.07.2015, 16:59
  #44

Не по теме:

Я ему про Фому ...

0
DrOffset
16.07.2015, 17:07     Проблема с указателем на элемент вектора
  #45

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Я ему про Фому ...
Я просто объяснил зачем это сделано.
А Фома - это "непривычно"? Ну так это нестрогое понятие. Кому-то и std:: непривычно и т.п. Что ж теперь не пользоваться std::?
В языке эта возможность существует именно для таких случаев, не вижу причин почему ее нужно игнорировать.

А случайное присваивание в if уже давно диагностируется всеми современными компиляторами, если предупреждения не отключать совсем.

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

Пользуясь указателем на массив целых чисел, найти минимальный и максимальный элемент массива - C++
Пользуясь указателем на массив целых чисел, найти минимальный и максимальный элемент массива. Использовать в программе арифметику...

Переделать функцию c указателем на int, на функцию с указателем на void - C++
Есть рабочий код qsort для int: void qsort(int *base, int n) { // Прекратить если количество элементов меньше либо равно единице....

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

Извлечь элемент из вектора - C++
Пожалуйста, помогите разобраться. Это функция разбивки строки на лексемы, и копирования результатов разбивки в вектор. void...


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

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

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