Не до конца понимаю о чём тут спор, но всё же спрошу - в стл именно поэтому в контейнерах можно опционально указывать некий аллокатор для этих целей?
бтв сомнительная опциональность, если честно.
pop работает неверно:
std::string s1 = "over9000", s2 = "ыыыыыы", s3; bStack<std::string> st; st.Push(s1 ); s3 = st.Pop( s1 ); st.Push( s2); // копия s1 не удалена, но затерта
Pokimon
очень лаконично ответил...
>В стек можно класть и вынимать.
>Что же делает эта функция?
дает ссылку на верхний элемент. А Pop должен быть либо void, либо возвращать значение, а не ссылку.
Ты определись стек у тебя для простых типов (которые просто данные) или для сложных тоже (с нетривиальными конструкторами\деструкторами).
Pokimon
Сделай другой стек.
Merrewend
> // копия s1 не удалена, но затерта
А что вы предлагаете? Затирать ее нулями?
Хмм.. хотя вы правы. При убиении стека и вызова delete[] будут вызваны деструкторы уже удаленный объектов.
Но как же быть?
Правка: хотя нет. Какие еще деструкторы. Помещенные же элементы были созданы не в стеке.
В общем я запутался.
Правка2:
Меня посетила мысль. Дума так сказать.
Стек это память, в которую добавляются уже созданные где-то элементы.
указатель на память у меня имеет тип этих объектов. Что по идее приводит к вызову их деструкторов.
Если сделать указатель типа unsigned char * и кастовать его в правильный тип всегда, кроме удаления. Так можно избавиться от проблемы деструкторов.
НО хотелось бы, чтобы при удалении стека корректо удалялось его содержимое.
Отсюда вывод: Стек структура сложная.
Как быть?
gexogen
> Ты определись стек у тебя для простых типов
Стек у меня класса универсал.
Pokimon
посмотри реализацию std::vector. При вызове std::vector::reserve(100), не создается 100 объектов, а только выделяется память для 100 объектов, у тебя же нет различия - память\объект, так что создаются и живут пустые (инициализированные дефолтным конструктором) объекты. Чтобы этого не было, выделять память нужно "malloc(size)" либо "new char(size)". Таким образом у тебя не будет кучи пустых объектов. При добавлении (Push) элемента, ты его конструируешь в выделенную память с помощью "new(ptr) StackType(item)", то есть вызываешь конструктор копирования (у тебя сейчас вызов дефолтного конструктора и operator=). При извлечении из стека (Pop), ты объект уничтожаешь деструктором (явно вызываешь ~StackType). В деструкторе стека удалять занятую память с помощью ~StackType для всех созданных объектов + free(память).
Таким образом в стеке будут только реально добавленные туда объекты, а его поведение предсказуемо.
gexogen
Только увеличивать стек не получится без пересоздания всех объектов :)
У Pokimon'а нет переполнения
Pokimon
Можно сделать односвязный список из нодов и пулом пустых нодов для скорости.
Merrewend
>Только увеличивать стек не получится без пересоздания всех объектов :)
кажется это не мне или ты не прочитал мой пост. Но раз уж затронули тему. После выделения новой памяти нужно сконструировать объекты в новой памяти (через конструктор копирования опять же, а не как у Pokimon дефолтным конструктом и memcpy), после чего удалить объекты из старой памяти и освободить старую память.
>У Pokimon'а нет переполнения
тоже не понял, о каком переполнении идет речь?
>Можно сделать односвязный список из нодов и пулом пустых нодов для скорости.
тогда надо будет создать новый топик: "Создан односвязный список нодов и пулом пустых нодов для скорости" :)
gexogen
Я о том, что по замыслу автора стек не переполняется, а увеличивается. И, видимо, он хотел просто копировать память, не пересоздавая ( не копируя т.е. ) объекты.
> После выделения новой памяти нужно сконструировать объекты в новой памяти (через
> конструктор копирования опять же, а не как у Pokimon дефолтным конструктом и memcpy),
> после чего удалить объекты из старой памяти и освободить старую память.
я о том же. Но это - медленно.
Поиск в стеке не нужен, и, следовательно, нет причин отказываться от списка. Кроме экономии памяти.
Alex_MIPT
> Не до конца понимаю о чём тут спор, но всё же спрошу - в стл именно поэтому в
> контейнерах можно опционально указывать некий аллокатор для этих целей?
STL-контейнеры этим аллокатором выделяют (и удаляют) память под свои внутренние нужды (под узлы списков, деревьев, под содержимое деков и массивов etc). Типы, выступающие параметрами шаблонов контейнеров при этом способа выделения памяти не меняют. Т.о. каждый класс управляет своей памятью самостоятельно. Классы STL всего лишь предоставляют готовый способ порулить этим процессом.
Учитывая отсутствие в STL элементарных быстрых аллокаторов (стековый, блоковый) и вообще средств управления выделением памяти пользуются этим очень редко.
Pokimon
1) плохо что внутренний буфер твоего стека может только увеличиваться.
2) твой Resize по факту резервирует место во внутреннем буфере, поэтому лучше бы ему называться Reserve или SetBufferSize;
3) методы Length и Size по смыслу трудно различимы. Вот хочу я понять сколько элементов в стеке, как мне понять какой из этих двух методов звать? Пойти почитать код стека? Совет: а) никогда не применять Length для обозначения размера массива; Length, имхо, может относиться только к строкам и к геометрическим отрезкам; б) число элементов в стеке называть Size (вариант для графоманов – ElementCount); в) размер буфера так и называть – BufferSize.
4) T Pop(); должен возвращать удаляемое значение не по ссылке. Должен быть метод T& Top(); который возвращает ссылку на вершину стека, ничего не удаляя;
5) где методы IsEmpty, Empty?
6) запрещать копировать стек – возможно, здравая идея. Однако, эффективный метод Move (а лучше ещё и Swap) у хорошего стека должен быть.
7) когда добавишь метод Top, не забудь добавить также константную его версию: const T& Top() const.
Pokimon
Открытые члены класса в заголовке должны быть написаны первыми, чтобы пользователь, если будет их смотреть, сразу видел то, что ему доступно, а не закрытые кишки класса.
Ещё я бы в конструкторе сразу выделил память под default_size элементов не дожидаясь вызова Push и сделал бы default_size равным не 1, а сразу, например, 10.
Вот это
if(!(alloced - leangth))
я бы заменил на простое и понятное
if(alloced == leangth)
Сейчас перед Pokimon'ом начнут открываться новые горизонты...
Pokimon
> =A=L=X=
> > Если "=" делали, значит это кому нибудь нужно?
> Это нужно для более удобочитаемой записи. Не более.
В пёрлы!
Тема в архиве.