Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / STL containers / 20 сообщений из 20, страница 1 из 1
14.08.2006, 11:06
    #33915714
VasTemp
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Наверно, этот вопрос уже обсуждался, но т.к. топика не нашел, задам еще раз :)

Необходимо хранить довольно объемные объекты классов и их потомков. Что лучше помещать в собственно контейнеры (list, vector etc): сами объекты или указатели на них?

Как я понимаю, есть минусы в обоих случаях.

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

хранение указателей:
- необходимость явного вызова деструкторов для удаляемых объектов; неработоспособность некоторых алгоритмов – remove (утечка памяти), fill, copy (копируются указатели, а не объекты)
- т.к. элементы модифицируемые, то конструкции с итераторами типа
Код: plaintext
1.
2.
for (iterator itr = array.begin(); itr != array.end(); itr++)
  (*itr)->do_something();
станогвятся невозможными, т.к. do_something изменяет объект, он перемещается в памяти, и itr++ адресует несуществующий объект.

Я правильно рассуждаю? Окончательный вопрос: какое из зол, по мнению All, меньше, и что все-таки лучше хранить: объекты или указатели?

Заранее спасибо.
...
Рейтинг: 0 / 0
14.08.2006, 13:31
    #33916323
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
shared_ptr
smart_ptr
...
Рейтинг: 0 / 0
14.08.2006, 14:23
    #33916553
blinded
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Gluk прав, но слишком краток. В контейнере можно хранить как объекты, так и указатели, но если вам понадобится полиморфное поведение объектов, поневоле придется сладывать туда указатели, а лучше чтобы избежать утечек памяти - smart pointer'ы. Один из представителей - std::auto_ptr.Если хочется узнать о них подробнее читайте Александреску Modern C++ design... Что касается алгоритмов почитайте внимательнее про STL, если вам надо глубокое копрование используйте вместо copy transform, вместо fill - generate ну и т.д
А вот что касается утверждения на счет изменения адреса объекта - не говорите об этом брльше никогда и никому. Адрес объекту дается раз и навсегда при аллокировании памяти под него, если у вас вдруг изменился адрес объекта - значит вы видите уже другой объект
...
Рейтинг: 0 / 0
14.08.2006, 14:34
    #33916599
VasTemp
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
blindedОдин из представителей - std::auto_ptr.
std::auto_ptr - это аналог boost::shared_ptr? А куда лучше склониться? ;)
А вот что касается утверждения на счет изменения адреса объекта - не говорите об этом брльше никогда и никому. Адрес объекту дается раз и навсегда при аллокировании памяти под него, если у вас вдруг изменился адрес объекта - значит вы видите уже другой объект
Это предположение я сделал из того, что этот код не работает
Код: plaintext
1.
2.
for (iterator itr = array.begin(); itr != array.end(); itr++)
  (*itr)->do_something();
а этот работает
Код: plaintext
1.
2.
for (int i =  0 ; i < array.size(); i++)
  array[i]->do_something();
...
Рейтинг: 0 / 0
14.08.2006, 14:58
    #33916686
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
VasTemp...Это предположение я сделал из того, что этот код не работает
Код: plaintext
1.
2.
for (iterator itr = array.begin(); itr != array.end(); itr++)
  (*itr)->do_something();
а этот работает
Код: plaintext
1.
2.
for (int i =  0 ; i < array.size(); i++)
  array[i]->do_something();


а полный текст приведите пожалуйста данного тэста...
имееться ввиду с объявлениями переменных участвующих в данном коде.

(круглый)
...
Рейтинг: 0 / 0
14.08.2006, 16:17
    #33916950
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
blindedGluk прав, но слишком краток.

google

авторstd::auto_ptr - это аналог boost::shared_ptr? А куда лучше склониться? ;)

НИКОГДА, НИКОГДА в этой задаче НЕ СКЛОНЯЙТЕСЬ к auto_ptr
...
Рейтинг: 0 / 0
14.08.2006, 21:12
    #33917621
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Ответ на этот вопрос однозначен - нужно хранить объекты в контейнерах по значению.
Просто потому что STL не поддерживает автоматическое уничтожение объектов при удалении их из коллекций. Что бы его поддержаТь, надо переопределить буквально все операции добавления/удаления. А это страшный геморой.

Однако если вас устроит реализация внешнего контроля за созданием и удалением объектов
(например, такая схема : объекты создаются, пихаются в контейнеры , обрабатываются, а затем все скопом удаляются) , то можно (и нужно) хранить в контейнерах указатели.

Вот такая у нас замечательная библиотека STL.
...
Рейтинг: 0 / 0
15.08.2006, 09:10
    #33917971
VasTemp
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
kolobok0а полный текст приведите пожалуйста данного тэста...
имееться ввиду с объявлениями переменных участвующих в данном коде.

Урезанный код выглядит так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
class Obj {
  int a;
public:
  Obj {a =  0 ;}
  void do_something() {a =  1 ;}
};

typedef vector<Obj*> array;

void a() {
  // работает
  for (int i =  0 ; i < array.size(); i++)
    array[i]->do_something();
  // не работает
  array::iterator itr, end = array.end();
  for (itr = array.begin(); itr != end; itr++)
    (*itr)->do_something();
}
...
Рейтинг: 0 / 0
15.08.2006, 10:52
    #33918259
ChameLe0n
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Что именно не работает? Приведи текст ошибки.

Вот урезанный кусок из моего класса:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class EventSubject {
...

       list<EventObserver*> observers;	
...
        void notify(Event event){
         	list<EventObserver*>::iterator it;
	        for(it=observers.begin(); it!=observers.end();it++)
		      (*it)->update(event);
        }

...
}

Отлично все работает!
...
Рейтинг: 0 / 0
15.08.2006, 15:47
    #33919309
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
VasTempУрезанный код выглядит так:....

к сожалению в нём нет тех вещей которые могут оказаться причиной...Что бы не терять время привожу Ваш кусочек и довесок к нему (некоторые имена подкорректированы - уж не обесудьте, если на просвет не совпадёт :) ). Весь код рабочий, проблем не наблюдаю...

Код: plaintext
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.
class Obj
{
	int a;
public:
	Obj(void)
	{
		a =  0 ;
	};
	void do_something()
	{
		a =  1 ;
	};
};
typedef vector<Obj*> vArray;



// бла-бла-бла... типа
main()



	vArray	arrayX;

	for(int k =  0 ; k <  10 ; k++)
	{
		Obj* po = new Obj;
		arrayX.push_back(po);
	}


  // работает
	for(unsigned int i =  0 ; i < arrayX.size(); i++)
	{
		arrayX[i]->do_something();
	}
  // не работает
	vArray::iterator itr, end = arrayX.end();
	for(itr = arrayX.begin(); itr != end; itr++)
	{
		(*itr)->do_something();
	}


в коде нет освобождения ресурсов. Думаю, что проблемы теперь будет легче найти у ВАс... Ищите в объявлениях, наполнении вектора и прочей чухне...


с уважением
(круглый)
...
Рейтинг: 0 / 0
01.09.2006, 11:55
    #33957959
JustVas
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
В продолжение темы (VasTemp - это я, просто пароль забыл :)
Локализовал падающий код:
Код: plaintext
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.
#include <vector>
#include <iostream>
using namespace std;

class X {
	int i;
public:
	X(int ii): i(ii) {cout << "+X " << i << endl;}
	~X() {cout << "-X " << i << endl;}
	void f();
};

vector<X*> gv;

void X::f() {
	if (i ==  1 ) {
		gv.push_back(new X( 2 ));
		gv.push_back(new X( 3 ));
		gv.push_back(new X( 4 ));
	}
}

int main() {
	gv.push_back(new X( 1 ));
	// здесь все нормально
	for(int z =  0 ; z < gv.size(); ++z)
		gv[z]->f();
	// здесь на втором проходе цикла itr "сбивается" и показывает на "мусор"
	for(vector<X*>::iterator itr = gv.begin(); itr != gv.end(); ++itr)
		(*itr)->f();
}
Со счетчком работает, а с итератором нет! Дело не в освобождении ресурсов, т.к. проблемы наступают до уничтожения объектов. Переделка X* на shared_ptr<X> и vector на deque, естественно, ничего не дает. Тестилось на BC6 и MSVS2005.

Научите глупого! Не могу понять, что не так! :(
...
Рейтинг: 0 / 0
01.09.2006, 12:46
    #33958171
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
жжош, естественно сбивается происходит ресайз вектора на осередном пуше и итераторы превращаются ... превращаются итераторы ...

в элегантные указатели х.з. куда
совершенно недетеменированно притом. Поставь резерве 100000 у вектора, результат приятно удивит :)

Кстати, а нафига такие половые извращения ???
...
Рейтинг: 0 / 0
01.09.2006, 12:59
    #33958245
JustVas
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Gluk (Kazan)жжош, естественно сбивается происходит ресайз вектора на осередном пуше и итераторы превращаются ... превращаются итераторы ...

в элегантные указатели х.з. куда
совершенно недетеменированно притом. Поставь резерве 100000 у вектора, результат приятно удивит :)
Нехорошо как-то: я считал, что работа итераторов основана на счетчиках, и они всегда указывают на заданный элемент (до его удаления, конечно). :(
Gluk (Kazan)Кстати, а нафига такие половые извращения ???
Это контейнер "действий", которые могут изменять существующие или порождать новые.
...
Рейтинг: 0 / 0
01.09.2006, 13:04
    #33958268
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Итератор вектора это (почти) всегда указатель. При ресайзе содержимое вектора перемещается. Ваше отношение к этому ничего не изменит. Так есть. И на то есть причины.
...
Рейтинг: 0 / 0
01.09.2006, 13:07
    #33958286
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
заведи дополнительный вектор, вливай новые элементы туда, после прохода цикла сливай. Желательно конечно алгоритмами а не циклами
...
Рейтинг: 0 / 0
01.09.2006, 13:08
    #33958298
Gluk (Kazan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Кстати, это не единственный сюрприз итераторы дека еще более странные. Они инвалидируются, а указатели полученные ранее из них остаются валидными :)
...
Рейтинг: 0 / 0
02.09.2006, 00:46
    #33959956
nikname
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
VasTempхранение самих объектов:
- при добавлении нового элемента контейнера объект нужно создать дважды: сначала собственно объект коструируется, а затем копируется в элемент контейнера. При большом размере объекта и их количестве могут начаться тормоза.

хранение указателей:
- необходимость явного вызова деструкторов для удаляемых объектов; неработоспособность некоторых алгоритмов – remove (утечка памяти), fill, copy (копируются указатели, а не объекты)
- т.к. элементы модифицируемые, то конструкции с итераторами типа

Когда вы храните указатели на объекты, то тратите память ещё и на указатели - если память критична, то это явно лишнее.

Мне кажется, что вам есть смысл оценить обём требуемой памяти и понять, что вам нужно оптимизировать - память или скорость.
...
Рейтинг: 0 / 0
02.09.2006, 10:56
    #33960070
blinded
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Какойто спор интересный что хранить, выбор простой если вам нужен контейнер с конкретным типом то лучше хранить сами объекты и то при условии что вас удовлетворяет стандартный аллокатор, если у вашего обекта нет открытого конструкторакопирования, а вы не готовы переписывать allocator выбора у вас нет - придется хранить указатели, аналогично придется хранить указатели ежели хочется получить полиморфное поведение объектов в контейнере.
Чтобы избежатть утечки ресурсов при хранении указателей, храните не указатель, а smart poiter
Чтобы не оказаться в положении автора топика, помните что есть операции которые инвалидируют итераторы.
И никогда не пфтайтесь удалить iterator end() - эффект потрясающий!
...
Рейтинг: 0 / 0
03.09.2006, 12:59
    #33960587
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
Стандартные аллокаторы не работают, они вообще бесполезны. Это так, просто напомнил.
...
Рейтинг: 0 / 0
03.09.2006, 14:54
    #33960643
nikname
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
STL containers
MasterZivСтандартные аллокаторы не работают, они вообще бесполезны. Это так, просто напомнил.
ПРоясните, пожалуйста.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / STL containers / 20 сообщений из 20, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]