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

Необходимо хранить довольно объемные объекты классов и их потомков. Что лучше помещать в собственно контейнеры (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
STL containers
    #33916323
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shared_ptr
smart_ptr
...
Рейтинг: 0 / 0
STL containers
    #33916553
Фотография blinded
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Gluk прав, но слишком краток. В контейнере можно хранить как объекты, так и указатели, но если вам понадобится полиморфное поведение объектов, поневоле придется сладывать туда указатели, а лучше чтобы избежать утечек памяти - smart pointer'ы. Один из представителей - std::auto_ptr.Если хочется узнать о них подробнее читайте Александреску Modern C++ design... Что касается алгоритмов почитайте внимательнее про STL, если вам надо глубокое копрование используйте вместо copy transform, вместо fill - generate ну и т.д
А вот что касается утверждения на счет изменения адреса объекта - не говорите об этом брльше никогда и никому. Адрес объекту дается раз и навсегда при аллокировании памяти под него, если у вас вдруг изменился адрес объекта - значит вы видите уже другой объект
...
Рейтинг: 0 / 0
STL containers
    #33916599
VasTemp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
STL containers
    #33916686
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
STL containers
    #33916950
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
blindedGluk прав, но слишком краток.

google

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

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

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

Вот такая у нас замечательная библиотека STL.
...
Рейтинг: 0 / 0
STL containers
    #33917971
VasTemp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
STL containers
    #33918259
ChameLe0n
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Что именно не работает? Приведи текст ошибки.

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

Код: 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
STL containers
    #33919309
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
STL containers
    #33957959
JustVas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В продолжение темы (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
STL containers
    #33958171
Фотография Gluk (Kazan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
жжош, естественно сбивается происходит ресайз вектора на осередном пуше и итераторы превращаются ... превращаются итераторы ...

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

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

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

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

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

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


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