Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Vector указателей

390
20 марта 2006 года
lexus
143 / / 13.04.2004
Имеется вектор указателей на CNode
CNode* node=new CNode(X,Y);
nodes.push_back(node);
Я удаляю так:
for (vector<CNode*>::iterator i=nodes.end()-1;i>=nodes.begin();i--){
delete (*i);
nodes.erase(i);
}
В процессе выполнения вылетает ошибка
Как правильно освободить память?
7.9K
20 марта 2006 года
uki_
122 / / 26.01.2006
nodes.erase() нужно бы убрать.
А за пределами цикла написать nodes.clear();
390
20 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by uki_
nodes.erase() нужно бы убрать.
А за пределами цикла написать nodes.clear();


Допустим.А как удалить только один элемент из векторА?

7.9K
20 марта 2006 года
uki_
122 / / 26.01.2006
Цитата:
Originally posted by lexus
Допустим.А как удалить только один элемент из векторА?

Один конечно через erase(), но сперва нужно с него "ступить". Что-то типа

Код:
vector<CNode*>::iterator j = nodes.end();
for(vector<CNode*>::iterator i=nodes.end()-1;i>=nodes.begin();i--)
{
  if(j!=nodes.end())
  {
    nodes.erase(j);
    j = nodes.end();
  }
  if(удалить_тек_элемент==true)j = i;
}
if(j!=nodes.end())nodes.erase(j);
390
20 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by uki_
Один конечно через erase(), но сперва нужно с него "ступить". Что-то типа
Код:
vector<CNode*>::iterator j = nodes.end();
for(vector<CNode*>::iterator i=nodes.end()-1;i>=nodes.begin();i--)
{
  if(j!=nodes.end())
  {
    nodes.erase(j);
    j = nodes.end();
  }
  if(удалить_тек_элемент==true)j = i;
}
if(j!=nodes.end())nodes.erase(j);


Спасибо, сейчас попробую

390
20 марта 2006 года
lexus
143 / / 13.04.2004
Старик, подскажи еще такой момент.
Если есть большой объект CNode, как лучше организовать программу:
vector<CNode*> nodes;
CNode* node=new CNode(X,Y);
nodes.push_back(node);

или
vector<CNode> nodes;
nodes.push_back(CNode(X,Y));
7.9K
20 марта 2006 года
uki_
122 / / 26.01.2006
В первом случае +4*n памяти, +дин.объекты, которых нужно потом отдельно удалять.

imho второй способ лучше.
390
20 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by uki_
В первом случае +4*n памяти, +дин.объекты, которых нужно потом отдельно удалять.

imho второй способ лучше.


Что такое n? Размер объекта?

7.9K
20 марта 2006 года
uki_
122 / / 26.01.2006
Цитата:
Originally posted by lexus
Что такое n? Размер объекта?

Нет. Число объектов Nodes. Это лишние указатели.

395
21 марта 2006 года
RelB
367 / / 09.11.2002
Цитата:
Originally posted by lexus
Имеется вектор указателей на CNode
CNode* node=new CNode(X,Y);
nodes.push_back(node);
Я удаляю так:
for (vector<CNode*>::iterator i=nodes.end()-1;i>=nodes.begin();i--){
delete (*i);
nodes.erase(i);
}
В процессе выполнения вылетает ошибка
Как правильно освободить память?


Вообще, хорошим стилем программирования в данном случае использовать смартпоинтеры...

390
21 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by RelB
Вообще, хорошим стилем программирования в данном случае использовать смартпоинтеры...


Можно с этого момента поподробнее?
Теперь новый вопрос:
Мне надо из итератора получить указатель на объект. Я пробую так
for (vector<CNode>::iterator i=nodes.begin();i<nodes.end();i++){
if (i->HitTest(X,Y)==true){
BeginDrag(reinterpret_cast<CNode*>(&i));
return false;
}
}
Но в ф-ю BeginDrag передается какой-то мусор
void CNodes::BeginDrag(CNode* node){
node->Assign(5,5);
}
Как правильно сделать и в чем сдесь ошибка?

7.9K
21 марта 2006 года
uki_
122 / / 26.01.2006
Код:
for(vector<CNode>::iterator i=nodes.begin();i!=nodes.end();i++)
{
  if (i->HitTest(X,Y)==true)
  {
    BeginDrag(i);
    return false;
  }
}

void CNodes::BeginDrag(CNode* node)
{
  node->Assign(5,5);   
}
390
21 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by uki_
Код:
for(vector<CNode>::iterator i=nodes.begin();i!=nodes.end();i++)
{
  if (i->HitTest(X,Y)==true)
  {
    BeginDrag(i);
    return false;
  }
}

void CNodes::BeginDrag(CNode* node)
{
  node->Assign(5,5);   
}


------ Build started: Project: First, Configuration: Debug Win32 ------
Compiling...
Node.cpp
c:\documents and settings\xxx\мои документы\visual studio 2005\projects\first\first\node.cpp(31) : error C2664: 'CNodes::BeginDrag' : cannot convert parameter 1 from 'std::_Vector_iterator<_Ty,_Alloc>' to 'CNode *'
with
[
_Ty=CNode,
_Alloc=std::allocator<CNode>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Build log was saved at "file://c:\Documents and Settings\XXX\Мои документы\Visual Studio 2005\Projects\First\First\Debug\BuildLog.htm"
First - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

7.9K
21 марта 2006 года
uki_
122 / / 26.01.2006
Цитата:
Originally posted by lexus
------ Build started: Project: First,
<skipped>

Странно. У меня в VC6 компилируется без проблем. Тогда наверно нужно изменить заголовок BeginDrag
void CNodes::BeginDrag(vector<CNode>::iterator node)

390
21 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by uki_
Странно. У меня в VC6 компилируется без проблем. Тогда наверно нужно изменить заголовок BeginDrag
void CNodes::BeginDrag(vector<CNode>::iterator node)



Жаль

7.9K
21 марта 2006 года
uki_
122 / / 26.01.2006
Цитата:
Originally posted by lexus
Жаль

На худой конец
BeginDrag(reinterpret_cast<CNode*>(i));

т.е. i без &.

406
21 марта 2006 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by uki_
На худой конец
BeginDrag(reinterpret_cast<CNode*>(i));

т.е. i без &.



А может все же просто так:
BeginDrag(&(*i));

для данного случая reinterpret_cast не требуется

16K
22 марта 2006 года
Vendigo
13 / / 22.03.2006
Цитата:
Originally posted by lexus
Имеется вектор указателей на CNode
CNode* node=new CNode(X,Y);
nodes.push_back(node);
Я удаляю так:
for (vector<CNode*>::iterator i=nodes.end()-1;i>=nodes.begin();i--){
delete (*i);
nodes.erase(i);
}
В процессе выполнения вылетает ошибка
Как правильно освободить память?



Во первых, при вызове erase итератор становится не действительниым, поэтому его использовать нельзя. Кстати все итераторы указывавшие на этот вектор становятся не действительными. Для этих целей метод erase возвращает новый итератор.
код цикла надо переписать так:
vector<CNode*>::iterator iter = nodes.begin();
while ( iter != nodes.end() )
{
delete *iter;
iter = nodes.erase(iter);
}

во вторых, ты в коде пытался удалить nodes.end() чего делать мягко говоря не желательно.
Во вторых всегда используй с итераторами префиксную форму вместо постфиксной, т.е. ++i вместо i++, т.к. не тратится время на создание предыдущей копии итератора.

Далее, насчёт выбора vector<CNode> и vector<CNode*>. Выбор должен исходить из того, насколько быстро выполняется копирование объекта Node. т.е.
CNode n1, n2;
n1 = n2; - эсли эта операция затратна, то следует предпочесть список указателей, т.к. в STL операция копирования наиболее часто используемая.

Насчёт умных указателей.
используй объект shared_ptr<T> из библиотеки boost, библиотеку можешь взять на сайте boost.org.

16K
22 марта 2006 года
Vendigo
13 / / 22.03.2006
for(vector<CNode>::iterator i=nodes.begin();i!=nodes.end();i++)
{
if (i->HitTest(X,Y)==true)
{
BeginDrag(&(*i)); - вот здесь поправил
return false;
}
}

void CNodes::BeginDrag(CNode* node)
{
node->Assign(5,5);
}
395
22 марта 2006 года
RelB
367 / / 09.11.2002
Цитата:
Originally posted by Vendigo
for(vector<CNode>::iterator i=nodes.begin();i!=nodes.end();i++)
{
if (i->HitTest(X,Y)==true)
{
BeginDrag(&(*i)); - вот здесь поправил
return false;
}
}

void CNodes::BeginDrag(CNode* node)
{
node->Assign(5,5);
}


А собственно, чем вам не нравится использовать

 
Код:
for(size_t i = 0, sz = nodes.size(); i < sz; i++)
{
   if(nodes->HitTest(X,Y))
   {
      BeginDrag(nodes);
      return false;
   }
}
16K
22 марта 2006 года
Vendigo
13 / / 22.03.2006
Цитата:
Originally posted by RelB
А собственно, чем вам не нравится использовать
 
Код:
for(size_t i = 0, sz = nodes.size(); i < sz; i++)
{
   if(nodes->HitTest(X,Y))
   {
      BeginDrag(nodes);
      return false;
   }
}



Всем нравится, просто обсуждение было в нотации итераторов.
А так если использование вектора оправдано, и не будет изменено в дальнейшем ни на что другое, то без проблем.
Тут можно полемику долго развивать, например for_each предложить, но я думаю остоновимся просто на работающем варианте

390
22 марта 2006 года
lexus
143 / / 13.04.2004
for(size_t i = 0, sz = nodes.size(); i < sz; i++)
{
if(nodes->HitTest(X,Y))
{
BeginDrag(nodes);
return false;
}
}
Я так вчера и сделал.Все работает ОК.Но чисто из теоретических интересов не пойму почем не работает мой вариант.

BeginDrag(&(*i)); - по-моему это извращение.Правда не проверял насчет работы.Почему тогда не работает просто BeginDrag(i) или в паре с reinterpret_cast?
16K
23 марта 2006 года
Vendigo
13 / / 22.03.2006
Цитата:

BeginDrag(&(*i)); - по-моему это извращение.Правда не проверял насчет работы.Почему тогда не работает просто BeginDrag(i) или в паре с reinterpret_cast?



Сделай параметр в BeginDrag не указателем, а ссылкой, и тогда будет запись BeginDrag(i);

406
23 марта 2006 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by Vendigo
Сделай параметр в BeginDrag не указателем, а ссылкой, и тогда будет запись BeginDrag(i);



Интересно это как же,так что ли:
void CNodes::BeginDrag(CNode& node)
{
node.Assign(5,5);
}

for(vector<CNode>::iterator i=nodes.begin();i!=nodes.end();i++)
{
if (i->HitTest(X,Y)==true)
{
BeginDrag(i);//Ошибка!!!
return false;
}
}

И это по твоему должно работать?!!

И еще

Цитата:

BeginDrag(&(*i)); - по-моему это извращение.Правда не проверял насчет работы.



Вот именно сначала проверь. Вообще то это самый правильный вариант для данного случая а не какое не извращение,если ты не умееш с итераторами обращяться то это не их вина.
Может лучше почитаеш немного Страуструпа.
К примеру:
class C{
...
int var;
};

vector<C> vc;
vector<C>::iterator it;

теперь мы можем обращяться из итератора к переменной var так:
it->var=0;
int i = it->var;
или
(*it).var=0;
int i = (*it).var;

Теперь что касается * и -> это идут операторы разыменовывания итератора т.е. получение реального объекта на что указывает итератор в данный момент. т.е. в данном случае *it эквивалентно как если бы мы просто имели переменную типа (C mv) mv есть *it,и соответсвенно поэтому в твоем случае мы использовали конструкцию &(*it) что эквивалентно в случае с обычной переменной &mv.
Надеюсь хоть что то понятно,за остальным хотя бы к страуструпу.

16K
24 марта 2006 года
Vendigo
13 / / 22.03.2006
Цитата:
Originally posted by vitaly2003s
Интересно это как же,так что ли:
void CNodes::BeginDrag(CNode& node)
{
node.Assign(5,5);
}

for(vector<CNode>::iterator i=nodes.begin();i!=nodes.end();i++)
{
if (i->HitTest(X,Y)==true)
{
BeginDrag(i);//Ошибка!!!
return false;
}
}

И это по твоему должно работать?!!



Вобще то вызов должен быть такой BeginDrag(*i);
т.к. сначала надо разыменовать указатель, это и имелось ввиду. Следующий раз буду свои слова дополнять кодом, просто думал и так будет всё понятно.

Цитата:
Originally posted by vitaly2003s

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



А это всё к чему или кому адресовывалось?

390
29 марта 2006 года
lexus
143 / / 13.04.2004
Уважаемый vitaly2003s,давай только не будем отсылать к Страустрапу, по-моему форумы существуют для того, чтоб учиться, а не для того, чтоб умничать, не посоветовав ничего путнего.
406
29 марта 2006 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by lexus
Уважаемый vitaly2003s,давай только не будем отсылать к Страустрапу, по-моему форумы существуют для того, чтоб учиться, а не для того, чтоб умничать, не посоветовав ничего путнего.


Ну еслидаже непонятно было что я описал про разыменование о чем ты даже и не подозревал,то страуструп тут бессилен.

390
29 марта 2006 года
lexus
143 / / 13.04.2004
Цитата:
Originally posted by vitaly2003s
Ну еслидаже непонятно было что я описал про разыменование о чем ты даже и не подозревал,то страуструп тут бессилен.


BeginDrag(&(*i));
Это ты называешь разыменованием?Это то же самое, что a+1-1+2-2,в смысле, две противоположные операции, и не надо говорить, о чем я подозревал, а о чем нет.Тем более, что твой вариант не подошел

16K
30 марта 2006 года
Vendigo
13 / / 22.03.2006
Цитата:
Originally posted by lexus
BeginDrag(&(*i));
Это ты называешь разыменованием?Это то же самое, что a+1-1+2-2,в смысле, две противоположные операции, и не надо говорить, о чем я подозревал, а о чем нет.Тем более, что твой вариант не подошел



Это не тоже самое.
Смотрим по шагам.
i - имеет тип vector<CNode>::iterator.
это итератор, это не указатель в общем смысле, хотя многие реализации вектора для DEBUG и все для RELEASE реализуют это как указатель. Но в любом случае это итератор.
*i - операция разъименовывания итератора, т.е. имеет тип CNode.
Твоя функция хочет тип CNode*, поэтому нужно получить адрес объекта,
т.е. &(*i).
как видим i имеет тип vector<CNode>::iterator
а &(*i) имеет тип CNode*.
В общем случае это разные вещи.

406
30 марта 2006 года
vitaly2003s
481 / / 27.07.2004
Pravilno vendigo,etot lexus upersya kak baran i prosteishi veshei ne hochet ponyat. Ne znaya o chem govorit on eshe i sporit. Vse zakrili temu.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог