навеяло про boost::lexical_cast и схожие темы.
Знаю что баян, но ответа так толком для себя не сформулировал.
Возьмем к примеру std::vector. Требует copy ctor и потому часто приходится держать в нем shared_ptr. Наверное будет move ctor в будущем. Но непонятно другое — 95% (а может и больше) применений вполне обошлись бы простым realloc. Почему было не предоставить пользователю право выбора?
аналогично с deque и размером непрерывной области.
Может есть какие-то глубинные причины и я просто туплю, но я не понимаю почему я должен платить за тот выбор который мне не подходит?
Здравствуйте, WiseAlex, Вы писали:
WA>навеяло про boost::lexical_cast и схожие темы. WA>Знаю что баян, но ответа так толком для себя не сформулировал. WA>Возьмем к примеру std::vector. Требует copy ctor и потому часто приходится держать в нем shared_ptr. Наверное будет move ctor в будущем. Но непонятно другое — 95% (а может и больше) применений вполне обошлись бы простым realloc. Почему было не предоставить пользователю право выбора? WA>аналогично с deque и размером непрерывной области.
realloc будет работать только для POD. И, вообще говоря, нет принципиальной проблемы сделать соответствующую специализацию std::vector для подов, чтоб она делала именно realloc, так что ты проверь, вдруг в твоей реализации STL это уже сделано.
Но shared_ptr — это не POD, и применять к нему realloc нельзя.
P.S. У тебя 95% типов в программе — поды?
WA>Может есть какие-то глубинные причины и я просто туплю, но я не понимаю почему я должен платить за тот выбор который мне не подходит?
Спокойнее, ты никому ничего не должен
Я вот не могу одного понять — что, в стандарте написано что-то вроде "использование контейнера/алгоритма не из STL — undefined behavior"?
Подходит для твоих целей — используй на здоровье.
Не подходит — используй своё.
А то каждый второй приходит на форум и выступает, что, мол, STL не дает мне использовать мой супер-контейнер или там запрещает писать цикл for( ; ; )
Здравствуйте, jazzer, Вы писали:
J>realloc будет работать только для POD. И, вообще говоря, нет принципиальной проблемы сделать соответствующую специализацию std::vector для подов, чтоб она делала именно realloc, так что ты проверь, вдруг в твоей реализации STL это уже сделано.
а в каких есть? по-моему с оптимизацией заморачивается только stl-port
J>Но shared_ptr — это не POD, и применять к нему realloc нельзя. J>P.S. У тебя 95% типов в программе — поды?
для большого количества типов relloc будет вполне успешно работать
у меня часто shared_ptr в векторе появляется когда необходим хранить большие типы — например std::vector<std::vector> — не виже причин по которым здесь не буде работать realloc
WA>>Может есть какие-то глубинные причины и я просто туплю, но я не понимаю почему я должен платить за тот выбор который мне не подходит?
J>Спокойнее, ты никому ничего не должен J>Я вот не могу одного понять — что, в стандарте написано что-то вроде "использование контейнера/алгоритма не из STL — undefined behavior"? J>Подходит для твоих целей — используй на здоровье. J>Не подходит — используй своё. J>А то каждый второй приходит на форум и выступает, что, мол, STL не дает мне использовать мой супер-контейнер или там запрещает писать цикл for( ; ; )
фактически я всего лишь спросил почему при проектировании stl было принято именно такое решение.
Использовать свое- это понятно . Просто удивляет, что возможность задавать аллокатор есть а других возможностей настройки нет.
Здравствуйте, jazzer, Вы писали:
J>Но shared_ptr — это не POD, и применять к нему realloc нельзя.
А почему, собственно? Какие к этому есть препятствия?
J>А то каждый второй приходит на форум и выступает, что, мол, STL не дает мне использовать мой супер-контейнер или там запрещает писать цикл for( ; ; )
Ну спрашиваете -- отвечаем
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
J>>Но shared_ptr — это не POD, и применять к нему realloc нельзя. E>А почему, собственно? Какие к этому есть препятствия?
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>Но shared_ptr — это не POD, и применять к нему realloc нельзя. E>А почему, собственно? Какие к этому есть препятствия?
Потому что есть user-defined destructor (в котором, собственно, и происходит удаление объекта, без него смысла в shared_ptr немного).
J>>А то каждый второй приходит на форум и выступает, что, мол, STL не дает мне использовать мой супер-контейнер или там запрещает писать цикл for( ; ; ) E>Ну спрашиваете -- отвечаем
Здравствуйте, jazzer, Вы писали:
J>Потому что есть user-defined destructor (в котором, собственно, и происходит удаление объекта, без него смысла в shared_ptr немного).
Здравствуйте, WiseAlex, Вы писали:
WA>Здравствуйте, jazzer, Вы писали:
J>>Потому что есть user-defined destructor (в котором, собственно, и происходит удаление объекта, без него смысла в shared_ptr немного).
WA>можно пояснить как на это воздействует realloc ?
realloc можно использовать только для подов, а тип с определенным деструктором — это не под.
По стандарту.
Естественно, в определенных компиляторах это может работать, но гарантий, понятно, никаких.
Здравствуйте, jazzer, Вы писали:
J>realloc можно использовать только для подов, а тип с определенным деструктором — это не под. J>По стандарту.
J>Естественно, в определенных компиляторах это может работать, но гарантий, понятно, никаких.
Понятно что в общем случае не POD объект не может быть просто скопирован куском памяти,
но при копировании shared_ptr никаких user-defined деструкторов вроде не должно вызываться?
Здравствуйте, WiseAlex, Вы писали:
WA>если он используется в нескольких потоках (ИМХО)
В смысле? Пример кода не покажешь?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>>>Но shared_ptr — это не POD, и применять к нему realloc нельзя. E>>А почему, собственно? Какие к этому есть препятствия? J>Потому что есть user-defined destructor (в котором, собственно, и происходит удаление объекта, без него смысла в shared_ptr немного).
Ну мы вызовем деструктор у "передвинутой" realloc'ом копии. Только и всего. В чём проблема-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
E>Ну мы вызовем деструктор у "передвинутой" realloc'ом копии. Только и всего. В чём проблема-то?
Проблема только в том, что по стандарту нельзя гарантировать, что это будет работать.
Больше проблем никаких.
Здравствуйте, jazzer, Вы писали:
E>>Ну мы вызовем деструктор у "передвинутой" realloc'ом копии. Только и всего. В чём проблема-то? J>Проблема только в том, что по стандарту нельзя гарантировать, что это будет работать. J>Больше проблем никаких.
IMHO -- это баг в стандарте. Есть какие-то объективные проблемы?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, WiseAlex, Вы писали:
WA>навеяло про boost::lexical_cast и схожие темы. WA>Знаю что баян, но ответа так толком для себя не сформулировал. WA>Возьмем к примеру std::vector. Требует copy ctor и потому часто приходится держать в нем shared_ptr. Наверное будет move ctor в будущем. Но непонятно другое — 95% (а может и больше) применений вполне обошлись бы простым realloc. Почему было не предоставить пользователю право выбора? WA>аналогично с deque и размером непрерывной области. WA>Может есть какие-то глубинные причины и я просто туплю, но я не понимаю почему я должен платить за тот выбор который мне не подходит?
Бодатся с stl — пустая трата времени. Более продуктивно использовать свои велосипеды и настраивать их по своим нуждам.
По теме: vector для POD и вектор для обьектов — это два разных контейнера, и в одну кучу их лучше не валить.
например для вектора с POD можно делать ресайз не инициализируя данные. это уместно если, например, ты инициализируешь данные сам в цикле строчкой ниже.
для обьектов в общем случая предварительная инициализация обязательна.
vector<shared_ptr> — фейлдизайн. лучше использовать умный контейнер если это возможно.
кроме всего прочего stl была включена в стандарт в слишком сыром состоянии и теперь поезд уже ушел.
немаловажно так же, что stl разрабатывал человек с религиозной неприязнью к ООП и непонятно для кого, поэтому некоторые вещи сделаны мягко говоря неадекватно.
то что не вписалось в концепцию итераторов не было включено вообще. Например двумерные массивы. Дефолтный dictionary (std::map) использует заведомо проигрышную схему: красно-черные деревья вместо хэширования. Видимо Степанов посчитал С++ программистов неспособными написать хеш-функцию или же хеш не вписался в чистоту концепции.
Так же некоторые хорошие идеи получили отвратительную реализацию, например, аллокатор — хорошая идея, но как это реализованно? если планируется использование аллокаторов, то фактичеески любая функция должна быть шаблонной
это позволит использовать аллокаторы, но такую функцию уже не бросишь в cpp-файл.
Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти и несколько шаблонных реализаций с аллокаторами.
Для себя я написал велосипед постренный по таким принципам и позволяющий использовать статический буффер на борту вектора
void get_some_data(ArrayRef<double> &result);
void test()
{
Array<double,20> res; // 20 элементов в статическом буффере, если не хватает делаем malloc
get_some_data(res);
}
Имхо, проблем настолько много, что разумным решением было бы переписать весь stl с белого листа, чем продолжать городить огород вокруг.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
E>>>Ну мы вызовем деструктор у "передвинутой" realloc'ом копии. Только и всего. В чём проблема-то? J>>Проблема только в том, что по стандарту нельзя гарантировать, что это будет работать. J>>Больше проблем никаких.
E>IMHO -- это баг в стандарте. Есть какие-то объективные проблемы?
баг или не баг — таково реальное положение дел.
Если у тебя есть компилятор, у которого явно прописано, в каком случае объекты можно двигать, даже если они не удовлетворяют условиям POD (у тебя есть такой компилятор?) — ради бога, пиши нестандартный код и пользуйся им на здоровье, никто не запрещает.
Объективная проблема — данные, которые могут лежать по отрицательному смещению. realloc, естественно, ничего о них не знает.
Наверняка еще можно вспомнить проблем, если подумать.
Здравствуйте, WiseAlex, Вы писали:
WA>Здравствуйте, jazzer, Вы писали:
J>>realloc можно использовать только для подов, а тип с определенным деструктором — это не под. J>>По стандарту.
J>>Естественно, в определенных компиляторах это может работать, но гарантий, понятно, никаких.
WA>Понятно что в общем случае не POD объект не может быть просто скопирован куском памяти, WA>но при копировании shared_ptr никаких user-defined деструкторов вроде не должно вызываться?
Здравствуйте, jazzer, Вы писали:
J>Объективная проблема — данные, которые могут лежать по отрицательному смещению. realloc, естественно, ничего о них не знает. J>Наверняка еще можно вспомнить проблем, если подумать.
Мы всё ещё о буфере std::vector? Или уже о чём-то ещё? Данных по отрицательному смещению у объекта быть не может из-за того, что объекты можно складывать в массивы
Вообще-то всё ровно наоборот, я не знаю компиляторов, у которых возникнут проблемы при бинарном перемещении вектора из shared_ptr'ов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
А почему красно-черные деревья заведомо более проигрышные чем хеш таблица? Вы уверены 100%, что std::map должен был быть обязательно построенным на основе хеш-таблиц?
> то что не вписалось в концепцию итераторов не было включено вообще. Например двумерные массивы.
Почему же к таким коллекциям нельзя применить концепцию итераторов?
— итератор по одному измерению — т.е. разыменуемый в одномерный массив и итератор по одномерному массиву. Можно так же написать итератор для обхода всего двухмерного массива, кто против?
Или я чего то не понимаю?
Здравствуйте, Erop, Вы писали:
WA>>если он используется в нескольких потоках (ИМХО) E>В смысле? Пример кода не покажешь?
Мда. внимательнее подумав — полагаю, что погорячился
Здравствуйте, StevenIvanov, Вы писали:
SI>Или я чего то не понимаю?
Ну вопрос прост: "Почему в STL нет эффективных многомерных массивов?".
ОТвет Клюева мне кажется правдоподобным, а тебе, насколько я понял, нет. Возможно ты знаешь ответ получше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, WiseAlex, Вы писали:
WA>Здравствуйте, jazzer, Вы писали:
J>>а компилятору откуда об этом знать? WA>так и я об этом — пусть пользователь решает
и в каком виде ты хочешь, чтоб он решал?
если через шаблонный параметр — это вешалка для пользователей, потому что все типы перестанут быть совместимыми.
Мне бы лично подошел какой-нть специальный traits — ну так их реализации STL и сейчас вольны определить и отдать тебе на специализацию.
Здравствуйте, Kluev, Вы писали:
K>Бодатся с stl — пустая трата времени. Более продуктивно использовать свои велосипеды и настраивать их по своим нуждам.
у меня stl вызывает двоякое чувство. С одной стороны меня вполне устраивают итераторы и другие концепции stl, с другой stl часто противоречит духу с++ — не платить за то что не используешь — все сделано для худшего случая и совершенно не понятно как это настроить для простых вариантов (только не рассказывайте опять, что мне нужно писать специализацию контейнера для легкой модификации его поведения (я не полный мазохист ).
По поводу своих велосипедов — когда выхода нет, то полностью согласен, но велосипед для наиболее частого случая — это уже слишком
Здравствуйте, jazzer, Вы писали:
J>и в каком виде ты хочешь, чтоб он решал? J>если через шаблонный параметр — это вешалка для пользователей, потому что все типы перестанут быть совместимыми.
и да и нет — такая совместимость нужна при копировании всего контейнера или в конструкторе копирования(решаемо)
в любом случае это не самый идеальный вариант J>Мне бы лично подошел какой-нть специальный traits — ну так их реализации STL и сейчас вольны определить и отдать тебе на специализацию.
вполне — только вот смысл? — в одной stl это заработает в другой нет. Почему бы это не включить в стандарт — или c0x это уже сделано?
по мне вполне бы подошел вариант и с указанием поведения в конструкторе — аналогично как реализован деструктор в shared_ptr. Впрочем, вероятно, здесь много подводных камней
Здравствуйте, WiseAlex, Вы писали:
J>>Мне бы лично подошел какой-нть специальный traits — ну так их реализации STL и сейчас вольны определить и отдать тебе на специализацию. WA>вполне — только вот смысл? — в одной stl это заработает в другой нет.
Ну потому что я хочу, чтоб мой код работал с любой STL
WA>Почему бы это не включить в стандарт — или c0x это уже сделано?
Нет, не сделано. Сделаны двигающие конструкторы и type_traits из boost (там, я думаю, есть is_pod<>).
Ты ж сам понимаешь, нельзя объять необъятное.
WA>по мне вполне бы подошел вариант и с указанием поведения в конструкторе — аналогично как реализован деструктор в shared_ptr.
Не только деструктор, но и аллокатор для счетчика.
WA>Впрочем, вероятно, здесь много подводных камней
угу.
Подовостью все не ограничивается.
Например, в может быть такой под:
struct A
{
int a,b,c,d;
int *p;
};
где p может указывать на одну из a,b,c,d.
Вроде и под, а если переместишь — будет плохо.
Здравствуйте, Kluev, Вы писали:
K>Так же некоторые хорошие идеи получили отвратительную реализацию, например, аллокатор — хорошая идея, но как это реализованно? если планируется использование аллокаторов, то фактичеески любая функция должна быть шаблонной
K>
K>это позволит использовать аллокаторы, но такую функцию уже не бросишь в cpp-файл. K>Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти и несколько шаблонных реализаций с аллокаторами. K>Для себя я написал велосипед постренный по таким принципам и позволяющий использовать статический буффер на борту вектора
K>
K>void get_some_data(ArrayRef<double> &result);
K>void test()
K>{
K> Array<double,20> res; // 20 элементов в статическом буффере, если не хватает делаем malloc
K> get_some_data(res);
K>}
K>
Чтото я не пойму выгоды от Вашей реализации аллокатора. По моему приведенные выше примеры функции get_some_data не эквивалентны: первую можно параметризовать аллокатором, а вторую нет. Эквивалентный второй функции пример на stl выглядит так:
template<typename T>
class Array : public vector<T, fast_allocator<T> >
{
// c-tors
};
void get_some_data(Array<double> &result); //< функция не шаблоннаяvoid test()
{
Array<double> res; //< ну 20 дублов на стеке хранить нельзя, но с горя я не помру.
get_some_data(res);
}
По моему это просто другая реализация, без всяких плюсов или минусов. К тому же Фича хранения 20 значений на стеке сомнительна, чаще всего vector служит для хранения данных, а не для использования его как буфферного объекта. Вот стрингу это бы не повредило, кстати говоря такая оптимизация во многих реализация std::string имеется.
Здравствуйте, StevenIvanov, Вы писали:
SI>Здравствуйте, Kluev, Вы писали:
K>>...
SI>А почему красно-черные деревья заведомо более проигрышные чем хеш таблица? Вы уверены 100%, что std::map должен был быть обязательно построенным на основе хеш-таблиц?
операция вставки гораздо дешевле в хеш-таблице т.к. не требуется балансировка дерева, поиск (и удаление) зависит от того насколько хорошо подобрана хеш функция.
при небольшом числе элементов разницей можно пренебречь, но при увеличении их числа map начинает безнадежно отставать.
Здравствуйте, Critical Error, Вы писали:
CE>Здравствуйте, Kluev, Вы писали:
CE>Чтото я не пойму выгоды от Вашей реализации аллокатора. По моему приведенные выше примеры функции get_some_data не эквивалентны: первую можно параметризовать аллокатором, а вторую нет. Эквивалентный второй функции пример на stl выглядит так:
ArrayRef<T> — базовый класс
Array<T,N> : ArrayRef<T> — производный класс с буффером
ArrayA<T,Allocator> : ArrayRef<T> — производный класс с аллокатором
можно напрямую наследоватся от ArrayRef<T> и переопределить виртуальные функции выделения памяти.
для передачи в функцию по ссылке используется базовый класс ArrayRef<T> поэтому можно иметь одну нешаблонную сигнатуру функции
недостатоки этой схемы: + vtbl в класс и чуть более медленный вызов виртуальных функций при изменении размера.
Здравствуйте, jazzer, Вы писали:
J>Объективная проблема — данные, которые могут лежать по отрицательному смещению. realloc, естественно, ничего о них не знает.
ничего там не лежит. Таблица виртуальных функций лежит по нулевому смещению. При наличии виртуального наследования она может быть размазана или типа того, но это совершенно другой случай.
Интересный патерн (или хак?) — есть набор классов одной длинны, с перегруженными функциями, а данные у всех одни, и эти классы помещены в вектор. При реалоке втаб переписывается и все ОК. Пример на тему — зачем нужен виртуальный конструктор копирования.
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, jazzer, Вы писали:
J>>Объективная проблема — данные, которые могут лежать по отрицательному смещению. realloc, естественно, ничего о них не знает.
P>ничего там не лежит. Таблица виртуальных функций лежит по нулевому смещению. При наличии виртуального наследования она может быть размазана или типа того, но это совершенно другой случай.
P>Интересный патерн (или хак?) — есть набор классов одной длинны, с перегруженными функциями, а данные у всех одни, и эти классы помещены в вектор. При реалоке втаб переписывается и все ОК. Пример на тему — зачем нужен виртуальный конструктор копирования.
в вектор ты их не положишь, т.к. при укладке в вектор они будут срезаны до типа указанного как аргумент шаблона.
их можно положить через placement new, но имхо такой подход уже попахивает фейлдизайном
в этой ситуации лучше иметь стековый распеределитель памяти для быстрой аллокации обьектов + массив указателей
Здравствуйте, Kluev, Вы писали:
K>ArrayRef<T> — базовый класс K>Array<T,N> : ArrayRef<T> — производный класс с буффером K>ArrayA<T,Allocator> : ArrayRef<T> — производный класс с аллокатором K>можно напрямую наследоватся от ArrayRef<T> и переопределить виртуальные функции выделения памяти. K>для передачи в функцию по ссылке используется базовый класс ArrayRef<T> поэтому можно иметь одну нешаблонную сигнатуру функции
K>недостатоки этой схемы: + vtbl в класс и чуть более медленный вызов виртуальных функций при изменении размера.
Хм... а ведь и правда хорошее решение. Чувствуется дух OOP/C++. Никаких подводных камней не заметно... Еслиб не было vtbl было бы вообще идеально, но, как говорится, чудес не бывает.
Более медленный вызов виртуальных функций — это не недостаток, нельзя его в таком контексте оценить, потому как функция то выполняет распределение памяти — чуть ли не самый сильный тормоз в C++. По сравнению с malloc-ом разница между прямым и виртуальным вызовом соврешенно никакая.
Честно сказать будь я единственным девелопером в проекте, я б сделал именно так. stl много кому не нравится, а я ее ее сторонник потому как она именно стандартная. Если я займусь велосипедостроительством в крупном проекте, это чтож получится — все юзают stl, а я что самый лысый штоли?
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>Объективная проблема — данные, которые могут лежать по отрицательному смещению. realloc, естественно, ничего о них не знает. J>>Наверняка еще можно вспомнить проблем, если подумать.
E>Мы всё ещё о буфере std::vector? Или уже о чём-то ещё? Данных по отрицательному смещению у объекта быть не может из-за того, что объекты можно складывать в массивы
ну для не-подов, опять же по стандарту, вообще не гарантируется непрерывность занимаемой ими памяти.
E>Вообще-то всё ровно наоборот, я не знаю компиляторов, у которых возникнут проблемы при бинарном перемещении вектора из shared_ptr'ов...
Что значит — не знаешь?
Ты все существующие компиляторы (и все их версии) протестировал?
У тебя есть гарантии отсутствия проблем (из документации, например, типа "мы гарантируем, что побитовое перемещение объекта всегда валидно независимо от того, под это или нет")?
Или это просто по результатам тестов?
В любом случае, никто не мешает тебе на тех компиляторах, которыми ты пользуешься, использовать realloc, если для них все работает.
Здравствуйте, Kluev, Вы писали:
K>Здравствуйте, StevenIvanov, Вы писали:
SI>>Здравствуйте, Kluev, Вы писали:
K>>>...
SI>>А почему красно-черные деревья заведомо более проигрышные чем хеш таблица? Вы уверены 100%, что std::map должен был быть обязательно построенным на основе хеш-таблиц?
K>операция вставки гораздо дешевле в хеш-таблице т.к. не требуется балансировка дерева, поиск (и удаление) зависит от того насколько хорошо подобрана хеш функция. K>при небольшом числе элементов разницей можно пренебречь, но при увеличении их числа map начинает безнадежно отставать.
При небольшом числе элементов хэш-таблицу использовать неразумно, т.к. сразу придется выделять память для всей таблицы. Вообще говоря для небольшого количества элементов разумнее использовать отсортированный массив, однако если говорить про некий общий случай деревья являются компромиссом.
Хэш таблицы, имхо, довольно специализированное решение, т.к. придется задуматься о размере таблицы, выборе хеш-функции, возможном числе коллизий и алгоритмах их разрешения. Для обобщенной реализации (опять же, имхо) деревья — это самое то.
... K>vector<shared_ptr> — фейлдизайн. лучше использовать умный контейнер если это возможно.
Далеко не факт что 'фейлдизайн'. shared_ptr это все же shared_ptr, со своей семантикой и возможностями, например: weak_ptr и возможностью указания своего deleter'a. При необходимости последнего, использование 'умного конетйнера' практически невозможно.
Если же речь идет о производительности, а конкретно о массовом изменении счетчиков ссылок при переаллокациях, то все не так страшно:
"Starting with Boost release 1.33.0, shared_ptr uses a lock-free implementation...", для однопоточных приложений можно переключиться на версию с ++ref_count(BOOST_SP_DISABLE_THREADS). Для выделения памяти под sp_counted_base имеется возможность задействовать quick_allocator(BOOST_SP_USE_QUICK_ALLOCATOR). А вообще — профайлер все покажет.
Вот еще цитата из "Technical Report on C++ Performance":
For example, if accessing a value through a trivial smart pointer is
significantly slower than accessing it through an ordinary pointer, the compiler is
inefficiently handling the abstraction. In the past, most compilers had significant
abstraction penalties and several current compilers still do. However, at least two
compilers have been reported to have abstraction penalties below 1% and another a
penalty of 3%, so eliminating this kind of overhead is well within the state of the art.
K>...Дефолтный dictionary (std::map) использует заведомо проигрышную схему: красно-черные деревья вместо хэширования.
Какая-то конкретная реализация может быть и не совсем оптимальна. Стандартом определена только сложность отдельных операций(logarithmic/ linear/constant/etc.) Конкретная реализация остается уделом производителей.
K>Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти
Получаем vtbl сотоварищи, и лишаемся no-throw гарантии для swap.
K>...Для себя я написал велосипед постренный по таким принципам и позволяющий использовать статический буффер на борту вектора
K>
K>void get_some_data(ArrayRef<double> &result);
K>void test()
K>{
K> Array<double,20> res; // 20 элементов в статическом буффере, если не хватает делаем malloc
K> get_some_data(res);
K>}
K>
Такая же техника применяется в некоторых реализация STL строк.
K>Имхо, проблем настолько много...
Большинство озвученных — следствия преждевременной оптимизации: "для вектора с POD можно делать ресайз не инициализируя данные", "vector<shared_ptr> — фейлдизайн", "map использует заведомо проигрышную схему".
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Здравствуйте, Kluev, Вы писали:
ЮЖ>... K>>vector<shared_ptr> — фейлдизайн. лучше использовать умный контейнер если это возможно. ЮЖ>Далеко не факт что 'фейлдизайн'. shared_ptr это все же shared_ptr, со своей семантикой и возможностями, например: weak_ptr и возможностью указания своего deleter'a. При необходимости последнего, использование 'умного конетйнера' практически невозможно.
если в контейнере лежат обьекты с разными deleter'aми, то это явный признак фейлдизайна.
K>>...Дефолтный dictionary (std::map) использует заведомо проигрышную схему: красно-черные деревья вместо хэширования. ЮЖ>Какая-то конкретная реализация может быть и не совсем оптимальна. Стандартом определена только сложность отдельных операций(logarithmic/ linear/constant/etc.) Конкретная реализация остается уделом производителей.
рассуждения о сферическом коне в вакууме. в реале std::map сильно проигрывает хеш таблице с хорошей хеш функцией. особенно если в качестве ключа строки.
K>>Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти ЮЖ>Получаем vtbl сотоварищи, и лишаемся no-throw гарантии для swap.
по сравнению с получеными удобствами не велика потеря.
K>>...Для себя я написал велосипед постренный по таким принципам и позволяющий использовать статический буффер на борту вектора
K>>
K>>void get_some_data(ArrayRef<double> &result);
K>>void test()
K>>{
K>> Array<double,20> res; // 20 элементов в статическом буффере, если не хватает делаем malloc
K>> get_some_data(res);
K>>}
K>>
ЮЖ>Такая же техника применяется в некоторых реализация STL строк.
только там все зашито в класс без возможности кастомизации. кастомизировать можно аллокатор и char_traits которые никому не нужны.
Здравствуйте, Kluev, Вы писали:
K>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Здравствуйте, Kluev, Вы писали:
ЮЖ>>... K>>>vector<shared_ptr> — фейлдизайн. лучше использовать умный контейнер если это возможно. ЮЖ>>Далеко не факт что 'фейлдизайн'. shared_ptr это все же shared_ptr, со своей семантикой и возможностями, например: weak_ptr и возможностью указания своего deleter'a. При необходимости последнего, использование 'умного конетйнера' практически невозможно.
K>если в контейнере лежат обьекты с разными deleter'aми, то это явный признак фейлдизайна.
А в чем тогда принципиальное отличие от объектов с 'virtual void release()' или с виртуальным деструктором?
K>>>...Дефолтный dictionary (std::map) использует заведомо проигрышную схему: красно-черные деревья вместо хэширования. ЮЖ>>Какая-то конкретная реализация может быть и не совсем оптимальна. Стандартом определена только сложность отдельных операций(logarithmic/ linear/constant/etc.) Конкретная реализация остается уделом производителей. K>рассуждения о сферическом коне в вакууме. в реале std::map сильно проигрывает хеш таблице с хорошей хеш функцией. особенно если в качестве ключа строки.
Без упоминания строк это тоже был сфероконь... Мне, например, куда важнее асимптотика различных операций чем разница констант в O-нотации. Имхо, первоочередные(при возможности) оптимизации — это смена алгоритмов с квадратичных на линейные или логарифмические, например. Это дает куда больший выигрыш чем оптимизация самих этих алгоритмов. Потом уже можно и профайлер подключать, аллокаторы менять и т.п.
K>>>Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти ЮЖ>>Получаем vtbl сотоварищи, и лишаемся no-throw гарантии для swap. K>по сравнению с получеными удобствами не велика потеря.
no-throw swap не велика потеря ?
K>>>...Для себя я написал велосипед постренный по таким принципам и позволяющий использовать статический буффер на борту вектора
... ЮЖ>>Такая же техника применяется в некоторых реализация STL строк. K>только там все зашито в класс без возможности кастомизации. кастомизировать можно аллокатор и char_traits которые никому не нужны.
А что в строках нужно кастомизировать ? Строки это вообще вещь такая... неоднозначная. каждому надо что-то свое кастомизировать.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Здравствуйте, Kluev, Вы писали:
K>>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>>Здравствуйте, Kluev, Вы писали:
ЮЖ>>>... K>>>>vector<shared_ptr> — фейлдизайн. лучше использовать умный контейнер если это возможно. ЮЖ>>>Далеко не факт что 'фейлдизайн'. shared_ptr это все же shared_ptr, со своей семантикой и возможностями, например: weak_ptr и возможностью указания своего deleter'a. При необходимости последнего, использование 'умного конетйнера' практически невозможно.
K>>если в контейнере лежат обьекты с разными deleter'aми, то это явный признак фейлдизайна. ЮЖ>А в чем тогда принципиальное отличие от объектов с 'virtual void release()' или с виртуальным деструктором?
Умный конетйнер может вызывать либо деструктор либо release. т.е. что-то одно. когда ты сказал что deleter-ы круче
очевидно предположить, что там "деструкторы" идут в перемешку с release.
ЮЖ>Без упоминания строк это тоже был сфероконь... Мне, например, куда важнее асимптотика различных операций чем разница констант в O-нотации. Имхо, первоочередные(при возможности) оптимизации — это смена алгоритмов с квадратичных на линейные или логарифмические, например. Это дает куда больший выигрыш чем оптимизация самих этих алгоритмов. Потом уже можно и профайлер подключать, аллокаторы менять и т.п.
а мне важнее время выполнения. обычно я просто создаю тест прикидываю верхний предел, умножаю на десять и смотрю, что получится.
кстати у меня есть старый большой тормозящий мап на 100к элементов написанный давным-давно, все никак не доходят руки выкинуть его и зменить на хеш. когда наконец выкину обязательно напишу результаты. в качестве ключа — int
K>>>>Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти ЮЖ>>>Получаем vtbl сотоварищи, и лишаемся no-throw гарантии для swap. K>>по сравнению с получеными удобствами не велика потеря. ЮЖ>no-throw swap не велика потеря ?
Для одинаковых классов no-throw выполняется, к тому же обычно свап для векторов используют как move.
Надо просто писать вот так и будет щастье:
K>>>>...Для себя я написал велосипед постренный по таким принципам и позволяющий использовать статический буффер на борту вектора ЮЖ>... ЮЖ>>>Такая же техника применяется в некоторых реализация STL строк. K>>только там все зашито в класс без возможности кастомизации. кастомизировать можно аллокатор и char_traits которые никому не нужны. ЮЖ>А что в строках нужно кастомизировать ? Строки это вообще вещь такая... неоднозначная. каждому надо что-то свое кастомизировать.
внутренний буфер, например, кастомизировать нельзя. может у меня все строки размером гораздо больше чем этот буффер и смысла в нем для меня нет.
Здравствуйте, jazzer, Вы писали:
J>ну для не-подов, опять же по стандарту, вообще не гарантируется непрерывность занимаемой ими памяти.
Да, а что для таких объектов возвращает sizeof, например? Или что должен вернуть operator new?
Можешь привести примеры реализаций, где будут такого рода проблемы? Или хотя бы идеи таких платформ и реализаций?
Просто некоторые требования стандарта проистеккают из понятных особенностей тех или иных платформ, например запрет присваивать невалидные указатели или double вполне разумен.
А какие проблемы могут быть с размещением не POD'ов в памяти? Можешь привести хотя бы идею проблем?
В частности, насколько я понимаю стандарт гарантирует, что объект, созданный по new будет размещён начиная с адреса, который вернт operator new и будет занимать не более sizeof байт...
Понятно, что объет может содержать указатели внутрь себя, в том числе и неявные, но если он этого не делает, и нет указателей на объект или его внутренности где-то снаружи (что, AFAIK, запрещено семантикой std::vector), то его, по идее, можно перемещать бинарно...
E>>Вообще-то всё ровно наоборот, я не знаю компиляторов, у которых возникнут проблемы при бинарном перемещении вектора из shared_ptr'ов... J>Что значит — не знаешь?
То и значит, что компиляторов знаю много, под много платформ, а проблемы такой не знаю. И даже идей не имею из чего она могла бы проистечь...
Вот интересуюсь у коллег, может кто знает в чём может юыть источник геморра? Или это таки в комитете перебдели?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, StevenIvanov, Вы писали:
SI>При небольшом числе элементов хэш-таблицу использовать неразумно, т.к. сразу придется выделять память для всей таблицы. Вообще говоря для небольшого количества элементов разумнее использовать отсортированный массив, однако если говорить про некий общий случай деревья являются компромиссом.
Можно экспоненциально наращивать размер таблицы, при заполнении, например...
SI>Хэш таблицы, имхо, довольно специализированное решение, т.к. придется задуматься о размере таблицы, выборе хеш-функции, возможном числе коллизий и алгоритмах их разрешения. Для обобщенной реализации (опять же, имхо) деревья — это самое то.
Существует куча библиотек, где есть куча хэш-таблиц общего назначения. И всё-то у них хорошо, только у Степанова руки кривые были, и пришлось ему деревьями удовлетворять всех желающих...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: настройка stl
От:
Аноним
Дата:
16.06.08 19:30
Оценка:
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, StevenIvanov, Вы писали:
SI>>При небольшом числе элементов хэш-таблицу использовать неразумно, т.к. сразу придется выделять память для всей таблицы. Вообще говоря для небольшого количества элементов разумнее использовать отсортированный массив, однако если говорить про некий общий случай деревья являются компромиссом. E>Можно экспоненциально наращивать размер таблицы, при заполнении, например...
А можно пример такой расширяющейся таблицы? Мне вот просто интересно как она работает... Как использовать хэш в такой таблице (хэш обрезается по разному что ли ) А как коллизии разрешать?
Неужели и для 10-100 элементов можно будет использывать?
Здравствуйте, Аноним, Вы писали:
А>А можно пример такой расширяющейся таблицы? Мне вот просто интересно как она работает... Как использовать хэш в такой таблице (хэш обрезается по разному что ли ) А как коллизии разрешать? А>Неужели и для 10-100 элементов можно будет использывать?
Если мине не изменяет память, то даже в MFC такая есть...
А вообще-то в чём проблемы сузить хэш? Нужно просто как-то отобразить n к 1, например популярны бывают всякие волшебные манипуляции с битами, или остаток от деления на размер таблицы, правда тогда размер таблицы обычно как простое число выбирают...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Erop пишет:
> Существует куча библиотек, где есть куча хэш-таблиц общего назначения. И > всё-то у них хорошо, только у Степанова руки кривые были, и пришлось ему > деревьями удовлетворять всех желающих...
А че за наезды на Степанова не по делу — hash_map чем-то не устраивает
что ли?
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Аноним, Вы писали:
А>А можно пример такой расширяющейся таблицы? Мне вот просто интересно как она работает... Как использовать хэш в такой таблице (хэш обрезается по разному что ли ) А как коллизии разрешать? А>Неужели и для 10-100 элементов можно будет использывать?
хеш никогда не обрезается, просто индекс в таблице считается как hash%table_size.
а при изменении размера элементы переносятся в новую таблицу с новыми индексами.
Re[8]: настройка stl
От:
Аноним
Дата:
16.06.08 20:29
Оценка:
Здравствуйте, Kluev, Вы писали:
K>... K>хеш никогда не обрезается, просто индекс в таблице считается как hash%table_size. K>а при изменении размера элементы переносятся в новую таблицу с новыми индексами.
Но раз такая пъянка — сложно сказать что выгодней. При таком подходе балансировка дерева (которая по статистике бывает не чаще чем в 2-3 вставки) может показаться достаточно выгодной операцией
Или у вас есть конкретные цифры резльтатов экспериментов? Было бы любопытно взглянуть...
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Kluev, Вы писали:
K>>... K>>хеш никогда не обрезается, просто индекс в таблице считается как hash%table_size. K>>а при изменении размера элементы переносятся в новую таблицу с новыми индексами.
А>Но раз такая пъянка — сложно сказать что выгодней. При таком подходе балансировка дерева (которая по статистике бывает не чаще чем в 2-3 вставки) может показаться достаточно выгодной операцией
а в хеш-таблице еще реже. к томуже если ты примерно знаешь число элементов, то можешь сразу создать таблицу нужного размера и "балансировок" не будет вообще.
А>Или у вас есть конкретные цифры резльтатов экспериментов? Было бы любопытно взглянуть...
возьми сам и померяй, хотябы на стандартном stl
Здравствуйте, Kluev, Вы писали:
SI>>А почему красно-черные деревья заведомо более проигрышные чем хеш таблица? Вы уверены 100%, что std::map должен был быть обязательно построенным на основе хеш-таблиц?
K>операция вставки гораздо дешевле в хеш-таблице т.к. не требуется балансировка дерева, поиск (и удаление) зависит от того насколько хорошо подобрана хеш функция. K>при небольшом числе элементов разницей можно пренебречь, но при увеличении их числа map начинает безнадежно отставать.
Ты б не позорился со своей безграмотностью, вставка в hash table дешевле не из-за балансировки (RB-деревья требуют при вставке не более одного вращения), а потому что вставка в hash table занимает константное время, в то время как вставка в дерево требует логарифмического поиска места вставки. У дерева просто другие плюсы, типа отсортированность, гарантия логарифмичности вставки (в то время как в hash table константность амортизированная, ибо может возникнуть необходимость расширения таблицы). Короче нефиг сравнивать апельсины с яблоками.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>ну для не-подов, опять же по стандарту, вообще не гарантируется непрерывность занимаемой ими памяти. E>Да, а что для таких объектов возвращает sizeof, например? Или что должен вернуть operator new?
А стандарт почитать? Он возвращает размер элемента массива, если тебе вздумается сложить эти объекты во встроенный массив.
А new вообще возвращает указатель E>Можешь привести примеры реализаций, где будут такого рода проблемы? Или хотя бы идеи таких платформ и реализаций?
Интерпретатор С++, например.
Представь, что у тебя все объекты складываются компилятором куда-то в одному ему ведомое место (c целью последующей сборки мусора, например), а пользователю отдаются только типизированные хэндлы, все размером с long, независимо от того, сколько там данных в каждом объекте, ну и хранятся обратные указатели на все имеющиеся хэндлы.
Так что если ты хэндл физически переместишь, таблица обратных указателей станет невалидной (она апдейтится при вызове конструкторов/деструкторов).
E>Просто некоторые требования стандарта проистеккают из понятных особенностей тех или иных платформ, например запрет присваивать невалидные указатели или double вполне разумен. E>А какие проблемы могут быть с размещением не POD'ов в памяти? Можешь привести хотя бы идею проблем?
см. выше пример с хэндлами. E>В частности, насколько я понимаю стандарт гарантирует, что объект, созданный по new будет размещён начиная с адреса, который вернт operator new и будет занимать не более sizeof байт...
да, вопрос только в том, как понимать "размещен по адресу". Я это понимаю как "этот адрес можно разыменовать и обращаться к членам". E>Понятно, что объет может содержать указатели внутрь себя, в том числе и неявные, но если он этого не делает, и нет указателей на объект или его внутренности где-то снаружи (что, AFAIK, запрещено семантикой std::vector), то его, по идее, можно перемещать бинарно...
см. выше пример с хэндлами. Все в рамках семантики.
E>Или это таки в комитете перебдели?
В комитете, вообще-то, как раз разработчики компиляторов и сидят
Здравствуйте, jazzer, Вы писали:
J>>>ну для не-подов, опять же по стандарту, вообще не гарантируется непрерывность занимаемой ими памяти. E>>Да, а что для таких объектов возвращает sizeof, например? Или что должен вернуть operator new? J>А стандарт почитать? Он возвращает размер элемента массива, если тебе вздумается сложить эти объекты во встроенный массив. J>А new вообще возвращает указатель
То есть, ты хочешь ссказать, что такой код
char buffer[sizeof( T )];
delete new( buffer )T;
не валиден?
E>>Можешь привести примеры реализаций, где будут такого рода проблемы? Или хотя бы идеи таких платформ и реализаций? J>Представь, что у тебя все объекты складываются компилятором куда-то в одному ему ведомое место (c целью последующей сборки мусора, например), а пользователю отдаются только типизированные хэндлы, все размером с long, независимо от того, сколько там данных в каждом объекте, ну и хранятся обратные указатели на все имеющиеся хэндлы. J>Так что если ты хэндл физически переместишь, таблица обратных указателей станет невалидной (она апдейтится при вызове конструкторов/деструкторов).
Боюсь, что такая реализация не будет соответсвовать стандарту. По крайней мере будут большие проблемы с адресной арефметикой и с возможностью прекращать существование объета, путём разрушения или переиспользования хранилища. Да и вообще с самим по себе понятием storage для объекта этот подход не совсем совместим, IMHO. С new размещения, с массивами. С моделью памяти, опять же, будут проблемы, IMHO.
Скажем как ты будешь обрабатывать ситуацию, при которой ты создаёшь объект по new размещениея, а памячть в твоём "теневом хранилоище объектов" закончилась?
Кроме того такой подход, скорее всего ещё и не целесообразен. Для POD это всё вообще не годится, так как про размещение POD в памяти всё описано явно. Так что в реализации С++ по любому прийдётся иметь традиционную реализацию размещения объектов в памяти. А тогда и не понятно зачем бы тогда отдельный огород городить с не POD типами...
E>>В частности, насколько я понимаю стандарт гарантирует, что объект, созданный по new будет размещён начиная с адреса, который вернт operator new и будет занимать не более sizeof байт... J>да, вопрос только в том, как понимать "размещен по адресу". Я это понимаю как "этот адрес можно разыменовать и обращаться к членам".
Нет, любой указатель можно привести к const char* и получить доступ к бинарному представлению данных...
J>см. выше пример с хэндлами. Все в рамках семантики.
Не годится пример с хэндлами. Он не будет соответсвовать стандарту во многих местах. Да и с многими программами будет несовместим, очевидно. Кроме того, AFAIK, таких реализаций интерпретаторов С++ нет. Что, IMHO, и не удивительно...
E>>Или это таки в комитете перебдели? J>В комитете, вообще-то, как раз разработчики компиляторов и сидят
Ну перебдеть-то это не мешает? С невозможностью двигать содержимое std::vector по памяти перебдели же?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Sergey, Вы писали:
S>А че за наезды на Степанова не по делу — hash_map чем-то не устраивает S>что ли?
Да не устраивает. Тем, что в станадарт не попал...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Sergey, Вы писали:
S>>А че за наезды на Степанова не по делу — hash_map чем-то не устраивает S>>что ли? E>Да не устраивает. Тем, что в станадарт не попал...
уже попал.
А тогда они просто не успевали.
Спасибо, что есть уже то, что есть, а то могли бы еще лет 10 без стандарта сидеть, за обещание, что через 10 лет у нас будет стандарт, в котором будут и хеши, и интрузивные контейнеры, и встроенная лисп-машина.
Здравствуйте, jazzer, Вы писали:
J>уже попал.
Ещё не уже попал J>А тогда они просто не успевали.
Ну вполне повод для претензий, что надобаляли всяких "меганужных" в стандарте next_permutation, vector<bool> и вектор значений, который я не помню как зовут, а вот хэшей и многомерных массивов положить не успели
J>Спасибо, что есть уже то, что есть, а то могли бы еще лет 10 без стандарта сидеть, за обещание, что через 10 лет у нас будет стандарт, в котором будут и хеши, и интрузивные контейнеры, и встроенная лисп-машина.
Да просто отцы таки роднЫе!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>уже попал. E>Ещё не уже попал J>>А тогда они просто не успевали. E>Ну вполне повод для претензий, что надобаляли всяких "меганужных" в стандарте next_permutation, vector<bool> и вектор значений, который я не помню как зовут, а вот хэшей и многомерных массивов положить не успели
Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов.
J>>Спасибо, что есть уже то, что есть, а то могли бы еще лет 10 без стандарта сидеть, за обещание, что через 10 лет у нас будет стандарт, в котором будут и хеши, и интрузивные контейнеры, и встроенная лисп-машина. E>Да просто отцы таки роднЫе!
Ну так потому что всем нужно свое (причем в каждый момент времени — разное), и у каждого есть повод для обиды, что вот именно то, что нужно ему, положить и не успели.
Здравствуйте, jazzer, Вы писали:
J>Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов.
Плохой и неудобный.
J>>>Спасибо, что есть уже то, что есть, а то могли бы еще лет 10 без стандарта сидеть, за обещание, что через 10 лет у нас будет стандарт, в котором будут и хеши, и интрузивные контейнеры, и встроенная лисп-машина. E>>Да просто отцы таки роднЫе!
J>Ну так потому что всем нужно свое (причем в каждый момент времени — разное), и у каждого есть повод для обиды, что вот именно то, что нужно ему, положить и не успели.
Ну то есть ты не согласен с тем, что надо было не vector<bool> делать, а на hash_map усилия направить?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Erop пишет:
> S>А че за наезды на Степанова не по делу — hash_map чем-то не устраивает > S>что ли? > Да не устраивает. Тем, что в станадарт не попал...
Так это не к Степанову претензии, в его реализции STL вроде как сразу
hash_map был.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Erop, Вы писали:
E>>Здравствуйте, jazzer, Вы писали:
J>>>уже попал. E>>Ещё не уже попал J>>>А тогда они просто не успевали. E>>Ну вполне повод для претензий, что надобаляли всяких "меганужных" в стандарте next_permutation, vector<bool> и вектор значений, который я не помню как зовут, а вот хэшей и многомерных массивов положить не успели
J>Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов.
примечательно как valarray выпадает из общего стиля stl. если взять например string или vector:
template <class сhar_type, class unusefull_stuff, class additional_butthurt> class basic_string;
template <class elem_type, class unusefull_stuff> class vector;
в valarray почему-то нет ни аллокатора ни стандартного набора begin/end .
чесно говоря я так и не понял для чего нужен этот класс, прочитав что это "многомерный массив" как-то пытался его использовать как двумерный массив, но так и не понял как в нем обратится к элементу по индексу [i,j].
Так, на чем мы тут остановились...
E>То есть, ты хочешь ссказать, что такой код
char buffer[sizeof( T )];
E>delete new( buffer )T;
не валиден?
Почему не валиден? Откуда это следует?
E>>>Можешь привести примеры реализаций, где будут такого рода проблемы? Или хотя бы идеи таких платформ и реализаций? J>>Представь, что у тебя все объекты складываются компилятором куда-то в одному ему ведомое место (c целью последующей сборки мусора, например), а пользователю отдаются только типизированные хэндлы, все размером с long, независимо от того, сколько там данных в каждом объекте, ну и хранятся обратные указатели на все имеющиеся хэндлы. J>>Так что если ты хэндл физически переместишь, таблица обратных указателей станет невалидной (она апдейтится при вызове конструкторов/деструкторов). E>Боюсь, что такая реализация не будет соответсвовать стандарту. По крайней мере будут большие проблемы с адресной арефметикой и с возможностью прекращать существование объета, путём разрушения или переиспользования хранилища. Да и вообще с самим по себе понятием storage для объекта этот подход не совсем совместим, IMHO. С new размещения, с массивами. С моделью памяти, опять же, будут проблемы, IMHO.
Тут я никаких проблем не вижу. Адресная арифметика никуда не делась, просто она будет ходить по указателям на хэндлы.
Она все равно определена только для массивов, так что внутри объектов ее юзать некооректно.
Со storage вообще проблем не вижу.
E>Скажем как ты будешь обрабатывать ситуацию, при которой ты создаёшь объект по new размещениея, а памячть в твоём "теневом хранилоище объектов" закончилась?
Останавливать программу. Других вариантов стандарт не дает, из-за 18.4.1.3/1-3.
Если б позволяли — кинул бы bad::alloc.
E>Кроме того такой подход, скорее всего ещё и не целесообразен. Для POD это всё вообще не годится, так как про размещение POD в памяти всё описано явно. Так что в реализации С++ по любому прийдётся иметь традиционную реализацию размещения объектов в памяти. А тогда и не понятно зачем бы тогда отдельный огород городить с не POD типами...
Для подов он не просто не годится, он прямо запрещен.
Насчет огорода — это дело такое, ни ты, ни я не можем предсказать, кому когда что понадобится.
Как ты, так и я — мы занимаемся спекуляциями.
Другое дело, если бы у меня была именно такая "выстраданная" реализация — тогда бы я мог ее аргументированно защищать.
А так — ну вот есть в Стандарте такое ограничение, и все тут.
Если следуешь ему — твоя программа гарантированно (Стандартом) будет работать на любой мыслимой стандартной реализации С++.
Если нет — нет.
E>>>В частности, насколько я понимаю стандарт гарантирует, что объект, созданный по new будет размещён начиная с адреса, который вернт operator new и будет занимать не более sizeof байт... J>>да, вопрос только в том, как понимать "размещен по адресу". Я это понимаю как "этот адрес можно разыменовать и обращаться к членам". E>Нет, любой указатель можно привести к const char* и получить доступ к бинарному представлению данных...
ссылку на стандарт дашь?
J>>см. выше пример с хэндлами. Все в рамках семантики. E>Не годится пример с хэндлами. Он не будет соответсвовать стандарту во многих местах. Да и с многими программами будет несовместим, очевидно. Кроме того, AFAIK, таких реализаций интерпретаторов С++ нет. Что, IMHO, и не удивительно...
E>>>Или это таки в комитете перебдели? J>>В комитете, вообще-то, как раз разработчики компиляторов и сидят E>Ну перебдеть-то это не мешает? С невозможностью двигать содержимое std::vector по памяти перебдели же?
еще раз — на каких условиях ее реализовывать?
По умолчанию это можно делать только для подов, но и с подами беда — вот у меня прямо сейчас есть структуры с указателями внутрь, хоть и поды. Если их передвинуть — все слетит нафиг.
Стало быть, надо отдельный механизм предусматривать, правильно? А, во-первых, продумать, как это правильно сделать (вариантов куча, и с наскоку не видно, какой лучше), чтоб все удобно было — на это время нужно, а во-вторых, это оптимизация, а для начала надо предоставить базовую функциональность, что и было сделано.
K>чесно говоря я так и не понял для чего нужен этот класс, прочитав что это "многомерный массив" как-то пытался его использовать как двумерный массив, но так и не понял как в нем обратится к элементу по индексу [i,j].
через слайсы, или как они там называются.
Если ты знаком с BLAS, то не должно быть проблем (я не знаком и с многомерными массивами по долгу службы не общаюсь).
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов. E>Плохой и неудобный.
Чем плохой? Ты им пользовался? (Я — нет.)
Неудобный — возможно, но он следует традициям лучших на то время библиотек линейной алгебры (фортрановских, в основном), так что для профессионалов в оных он должен быть удобен (я так предполагаю).
J>>>>Спасибо, что есть уже то, что есть, а то могли бы еще лет 10 без стандарта сидеть, за обещание, что через 10 лет у нас будет стандарт, в котором будут и хеши, и интрузивные контейнеры, и встроенная лисп-машина. E>>>Да просто отцы таки роднЫе!
J>>Ну так потому что всем нужно свое (причем в каждый момент времени — разное), и у каждого есть повод для обиды, что вот именно то, что нужно ему, положить и не успели.
E>Ну то есть ты не согласен с тем, что надо было не vector<bool> делать, а на hash_map усилия направить?
Чтоб сделать vector<bool>, нужен час времени, а вот чтоб сделать хеш — тут надо думать очень много, потому что очень много вопросов возникает и придется очень много решений принимать.
А уж если ты меня спрашиваешь... Да, не согласен.
На мой взгляд, там в языке самом достаточно проблем, чтоб забить и на hash_map и все остальное (потому что все это доступно в других библиотеках и так), но зато сделать то, что нельзя сделать без поддержки со стороны языка (ту же паралаллельность, рефлексию, метапрограммирование, лямбды, замыкания, модули, динамические библиотеки и прочее). А хеш мне точно не уперся — реализаций достаточно, выбирай любую. Будет время — ОК, можно и вставить. Но после того, как сделано то, что действительно важно и не сделать иначе.
Имхо, в стандарте вообще достаточно было только зафиксировать, что в контейнерах должны быть объявлены определенные типы (типа value_type и iterator) и определенные методы (типа size и begin/end), а всем остальным вообще не заморачиваться, пока не решены остальные проблемы. Но раз уж предоставили референсные реализации вектора/сета/мапа — спасибо, остальное сами напишем. Кто ж виноват, что люди с какого-то бодуна решили, что эти несчастные три контейнера и 15 алгоритмов — это и все, что есть и будет, а все остальное — ни-ни, и вместо того, чтобы писать собственные контейнеры и алгоритмы, удовлетворяющие базовым требованиям по интерфейсу, извращаются через стандартные и потом матерятся на всех углах...
Хорошо, что есть вменяемые конторы типа адоба, которые это делают централизованно и выкладывают в общий доступ, и буст, который занимается тем же, только бесплатно.
Здравствуйте, jazzer, Вы писали:
E>>То есть, ты хочешь ссказать, что такой код
char buffer[sizeof( T )];
E>>delete new( buffer )T;
не валиден? J>Почему не валиден? Откуда это следует?
Из твоего утверждения, что объект может содержать данные по отрицательному смещению.
E>>Боюсь, что такая реализация не будет соответсвовать стандарту. По крайней мере будут большие проблемы с адресной арефметикой и с возможностью прекращать существование объета, путём разрушения или переиспользования хранилища. Да и вообще с самим по себе понятием storage для объекта этот подход не совсем совместим, IMHO. С new размещения, с массивами. С моделью памяти, опять же, будут проблемы, IMHO. J>Тут я никаких проблем не вижу. Адресная арифметика никуда не делась, просто она будет ходить по указателям на хэндлы. J>Она все равно определена только для массивов, так что внутри объектов ее юзать некооректно.
А если приватное поле -- массив? J>Со storage вообще проблем не вижу.
Проблема в том, что storage -- это память, занимаемая объектом. НИкакого "теневого storage" вроде как не предусмотрено
E>>Скажем как ты будешь обрабатывать ситуацию, при которой ты создаёшь объект по new размещениея, а памячть в твоём "теневом хранилоище объектов" закончилась? J>Останавливать программу. Других вариантов стандарт не дает, из-за 18.4.1.3/1-3.
А разве останавливать можно? J>Если б позволяли — кинул бы bad::alloc.
Мне кажется, что new размещениея не может не работать...
J>Насчет огорода — это дело такое, ни ты, ни я не можем предсказать, кому когда что понадобится. J>Как ты, так и я — мы занимаемся спекуляциями.
Ну я поэтому и написал "скорее всего" J>Другое дело, если бы у меня была именно такая "выстраданная" реализация — тогда бы я мог ее аргументированно защищать. J>А так — ну вот есть в Стандарте такое ограничение, и все тут.
Интересно бы понять чем оно вызвано. Я всё ещё думаю, что это баг.
E>>Нет, любой указатель можно привести к const char* и получить доступ к бинарному представлению данных... J>ссылку на стандарт дашь?
КОгда встречусь с текстом -- дам. Но, кроме описания того, к чему можно приводить указатели, стандарт ещё сожержит подробное очень описание работы перекрытых operator new/delete. И там очень активно используется идея занимаемой объектом памяти. Так что твоя реализация, IMHO, не пролезет
E>>Ну перебдеть-то это не мешает? С невозможностью двигать содержимое std::vector по памяти перебдели же? J>еще раз — на каких условиях ее реализовывать? J>По умолчанию это можно делать только для подов, но и с подами беда — вот у меня прямо сейчас есть структуры с указателями внутрь, хоть и поды. Если их передвинуть — все слетит нафиг.
Ну я тоже согласен, что возможность двигать объекты по памяти никак не связана с их POD'овостью...
J>Стало быть, надо отдельный механизм предусматривать, правильно? А, во-первых, продумать, как это правильно сделать (вариантов куча, и с наскоку не видно, какой лучше), чтоб все удобно было — на это время нужно, а во-вторых, это оптимизация, а для начала надо предоставить базовую функциональность, что и было сделано.
Без этого std:vector малоюзабелен .
Интересно было бы понимать зачем вообще было выбрано требование на элемент контейнера иметь семантику значения. Необъодимым оно не является, необременительным тоже...
Вообще в дизайне STL лично мне очень не нравится отсутсвие целенаправленности. Скажем вот добавили в контейнеры аллокаторы. При этом зачем это сделали не понятно. Ни возмоэность передать контейнеру конкретный пул памяти не предусмотрели, ни возможность гранулировать аллокации. Результат печальный -- аллокаторы есть, а толку нет. И так во многих очень местах
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
J>Чем плохой? Ты им пользовался? (Я — нет.) J>Неудобный — возможно, но он следует традициям лучших на то время библиотек линейной алгебры (фортрановских, в основном), так что для профессионалов в оных он должен быть удобен (я так предполагаю).
Ну вот я из FORTRAN пришёл к С++, а валуеареем так воспользоваться и не пришлось... В FORTRAN есть очень хорошие библиотеки линейной алгебры. Но хороши они не контейнерами, а алгеброй. При этом в языке есть некоторые трудности с работой с памятью, так что тащить массивы оттуда в С++ -- идея так себе...
J>Чтоб сделать vector<bool>, нужен час времени, а вот чтоб сделать хеш — тут надо думать очень много, потому что очень много вопросов возникает и придется очень много решений принимать.
Насколько я понимаю, комитет работает коллегиально. Так что затраты бюрократических усилий сравнимы. Да и сам текст стандарта родить тоже непросто.
J>На мой взгляд, там в языке самом достаточно проблем, чтоб забить и на hash_map и все остальное (потому что все это доступно в других библиотеках и так), но зато сделать то, что нельзя сделать без поддержки со стороны языка (ту же паралаллельность, рефлексию, метапрограммирование, лямбды, замыкания, модули, динамические библиотеки и прочее). А хеш мне точно не уперся — реализаций достаточно, выбирай любую. Будет время — ОК, можно и вставить. Но после того, как сделано то, что действительно важно и не сделать иначе.
Насколько я понимаю, всех этих запросов не было на момент создания языка. Когда принимали стандарт и STL, уже могли бы заняться чем-то полезным, а не замораживанием степановского поделия навека. Но, видимо, зоопарк библиотек достал больше, чем отсутствие рефлексии.
Только они STL не особо хороший приняли, так что как у всех библиотек были свои контейнеры, так и остались
Так что главную задачу они не выполнили
J>Имхо, в стандарте вообще достаточно было только зафиксировать, что в контейнерах должны быть объявлены определенные типы (типа value_type и iterator) и определенные методы (типа size и begin/end), а всем остальным вообще не заморачиваться, пока не решены остальные проблемы. Но раз уж предоставили референсные реализации вектора/сета/мапа — спасибо, остальное сами напишем. Кто ж виноват, что люди с какого-то бодуна решили, что эти несчастные три контейнера и 15 алгоритмов — это и все, что есть и будет, а все остальное — ни-ни, и вместо того, чтобы писать собственные контейнеры и алгоритмы, удовлетворяющие базовым требованиям по интерфейсу, извращаются через стандартные и потом матерятся на всех углах...
Не понятно на кой вообще связываться с этим набором сэмплов по программированию шаблонов функций, работающих поверх итераторов...
J>Хорошо, что есть вменяемые конторы типа адоба, которые это делают централизованно и выкладывают в общий доступ, и буст, который занимается тем же, только бесплатно.
+1
Хорошо, что кто-то пытается всё это развивать, но, IMHO, значительная часть буста развивается не совсем туда, а STL скорее препятствует развитию, а не способствует
Нормальные шаблоны (с рефлексией, там скажем, и всякими аттрибутами типов) добавить в С++ коммитет не затянул и в этот раз, кстати... Либо я не в курсе.
Скажем можно ли теперь будет проитерировать поля объекта-параметра шаблона? Или можно ли будет написать шаблон для всех конструкторов типа? Или ещё что-нибудь в таком роде?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
E>>>То есть, ты хочешь ссказать, что такой код
char buffer[sizeof( T )];
E>>>delete new( buffer )T;
не валиден? J>>Почему не валиден? Откуда это следует? E>Из твоего утверждения, что объект может содержать данные по отрицательному смещению.
так мы уже, вроде, не отрицательное смещение обсуждаем, а теневое хранение, а ему он не противоречит (по крайенй мере, я не вижу, как).
J>>Тут я никаких проблем не вижу. Адресная арифметика никуда не делась, просто она будет ходить по указателям на хэндлы. J>>Она все равно определена только для массивов, так что внутри объектов ее юзать некооректно. E>А если приватное поле -- массив?
И что? внутри этого массива — можно, а снаружи (внутри содержащего его объекта) — по-прежнему нельзя.
J>>Со storage вообще проблем не вижу. E>Проблема в том, что storage -- это память, занимаемая объектом. НИкакого "теневого storage" вроде как не предусмотрено
Что значит — "память, занимаемая объектом"? по стандарту, в смысле.
E>>>Скажем как ты будешь обрабатывать ситуацию, при которой ты создаёшь объект по new размещениея, а памячть в твоём "теневом хранилоище объектов" закончилась? J>>Останавливать программу. Других вариантов стандарт не дает, из-за 18.4.1.3/1-3. E>А разве останавливать можно?
останавливать всегда можно Это как переполнение стека: вроде и корректная программа, а дальше работать нельзя, потому что машина не тянет. Здесь точно такой же случай.
J>>Если б позволяли — кинул бы bad::alloc. E>Мне кажется, что new размещениея не может не работать...
по стандарту — да, я же и сказал, что не позволяет.
Да и в любом случае, даже если ты сейчас мне докажешь, что схема с теневым хранением несовместима со стандартом — это будет лишь означать несовместимость данной конкретной схемы. Вполне возможно, что существует другая(ие), которая будет самым лучшим решением в каких-нибудь экзотических условиях, и будет на 100% удовлетворять стандарту.
E>Интересно бы понять чем оно вызвано. Я всё ещё думаю, что это баг.
Ну, можно поспрашивать членов комитета, чем это вызвано. Я не знаю.
E>>>Нет, любой указатель можно привести к const char* и получить доступ к бинарному представлению данных... J>>ссылку на стандарт дашь? E>КОгда встречусь с текстом -- дам. Но, кроме описания того, к чему можно приводить указатели, стандарт ещё сожержит подробное очень описание работы перекрытых operator new/delete. И там очень активно используется идея занимаемой объектом памяти. Так что твоя реализация, IMHO, не пролезет
Ну, аргументируй цитатами, обсудим.
E>>>Ну перебдеть-то это не мешает? С невозможностью двигать содержимое std::vector по памяти перебдели же? J>>еще раз — на каких условиях ее реализовывать? J>>По умолчанию это можно делать только для подов, но и с подами беда — вот у меня прямо сейчас есть структуры с указателями внутрь, хоть и поды. Если их передвинуть — все слетит нафиг. E>Ну я тоже согласен, что возможность двигать объекты по памяти никак не связана с их POD'овостью...
J>>Стало быть, надо отдельный механизм предусматривать, правильно? А, во-первых, продумать, как это правильно сделать (вариантов куча, и с наскоку не видно, какой лучше), чтоб все удобно было — на это время нужно, а во-вторых, это оптимизация, а для начала надо предоставить базовую функциональность, что и было сделано. E>Без этого std:vector малоюзабелен .
И? Где твое предложение по настройке двигания содержимого? И уверен ли ты, что оно — единственно правильное и никто потом не скажет: "могли бы заняться чем-то полезным, а не замораживанием егоровского поделия навека?"
E>Интересно было бы понимать зачем вообще было выбрано требование на элемент контейнера иметь семантику значения. Необъодимым оно не является, необременительным тоже...
Безопасностью. Все остальные схемы предполагают ручное управление временем жизни элементов.
E>Вообще в дизайне STL лично мне очень не нравится отсутсвие целенаправленности. Скажем вот добавили в контейнеры аллокаторы. При этом зачем это сделали не понятно. Ни возмоэность передать контейнеру конкретный пул памяти не предусмотрели, ни возможность гранулировать аллокации. Результат печальный -- аллокаторы есть, а толку нет. И так во многих очень местах
Ну, аллокаторы еще только ленивый не пнул.
Но в то время просто еще не изобрели подходов типа тех, что применены в бусте (см. аллокаторы у boost::shared_ptr).
Кстати, в бусте новые методы были применены и для конструирования, см. boost::inplace_factory.
И, кстати, изначально буст появился как раз для хранения и доведения до состояния интеграции предложений в стандартную библиотеку.
Здравствуйте, jazzer, Вы писали:
E>>А если приватное поле -- массив? J>И что? внутри этого массива — можно, а снаружи (внутри содержащего его объекта) — по-прежнему нельзя. J>>>Со storage вообще проблем не вижу.
Ещё бывают объединения, кстати.
J>Что значит — "память, занимаемая объектом"? по стандарту, в смысле.
Читай вокруг operator new. Что именно он возвращает.
J>Да и в любом случае, даже если ты сейчас мне докажешь, что схема с теневым хранением несовместима со стандартом — это будет лишь означать несовместимость данной конкретной схемы. Вполне возможно, что существует другая(ие), которая будет самым лучшим решением в каких-нибудь экзотических условиях, и будет на 100% удовлетворять стандарту.
Окей, тогда значит в её обсуждении нет никакого смысла. IMHO, даказательнйо силы она всё равно не имеет, так что в том, что обсуждаемое ограничение в стандарте не есть акт перебдения ты меня не убедил.
E>>Без этого std:vector малоюзабелен . J>И? Где твое предложение по настройке двигания содержимого? И уверен ли ты, что оно — единственно правильное и никто потом не скажет: "могли бы заняться чем-то полезным, а не замораживанием егоровского поделия навека?"
Мои предложения были бы слишком поздно. Но были и не мои. Только толку не было.
E>>Интересно было бы понимать зачем вообще было выбрано требование на элемент контейнера иметь семантику значения. Необъодимым оно не является, необременительным тоже... J>Безопасностью. Все остальные схемы предполагают ручное управление временем жизни элементов.
Да? И как безопасность связана с копируемостью содержимого std::map, например?
E>>Вообще в дизайне STL лично мне очень не нравится отсутсвие целенаправленности. Скажем вот добавили в контейнеры аллокаторы. При этом зачем это сделали не понятно. Ни возмоэность передать контейнеру конкретный пул памяти не предусмотрели, ни возможность гранулировать аллокации. Результат печальный -- аллокаторы есть, а толку нет. И так во многих очень местах J>Ну, аллокаторы еще только ленивый не пнул.
Проблема не в том, что они плохи, и не придумали хороших, а в том, что добавили в стандарт не пойми что не пойми зачем.
J>И, кстати, изначально буст появился как раз для хранения и доведения до состояния интеграции предложений в стандартную библиотеку.
В этом смысле он безусловно позитивен. Один shared_ptr оправдывает его существование рядом с STL. Хотя, IMHO, именно уродливость STL породила буст. Но в основном буст -- это склад понравившихся кому-то экспериментов, а не хорошая библиотека или коллекция хороших библиотек.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Kluev, Вы писали:
... ЮЖ>>>>Далеко не факт что 'фейлдизайн'. shared_ptr это все же shared_ptr, со своей семантикой и возможностями, например: weak_ptr и возможностью указания своего deleter'a. При необходимости последнего, использование 'умного конетйнера' практически невозможно.
K>>>если в контейнере лежат обьекты с разными deleter'aми, то это явный признак фейлдизайна. ЮЖ>>А в чем тогда принципиальное отличие от объектов с 'virtual void release()' или с виртуальным деструктором?
K>Умный конетйнер может вызывать либо деструктор либо release. т.е. что-то одно.
Я немного о другом: по сути deleter это и есть "virtual void release()", т.е. он может иметь разную реализацию(как и виртуальный деструктор).
Здесь-то в чем фейлдизайн?
K>когда ты сказал что deleter-ы круче...
Это где я такое говорил ?
ЮЖ>>Без упоминания строк это тоже был сфероконь... Мне, например, куда важнее асимптотика различных операций чем разница констант в O-нотации. Имхо, первоочередные(при возможности) оптимизации — это смена алгоритмов с квадратичных на линейные или логарифмические, например. Это дает куда больший выигрыш чем оптимизация самих этих алгоритмов. Потом уже можно и профайлер подключать, аллокаторы менять и т.п.
K>а мне важнее время выполнения...
Мне тоже. только вот оно из асимтотики следует...
K>>>>>Имхо, более правильным решением были бы базовые классы контейнера с виртуальными функциями выделения/освобождения памяти ЮЖ>>>>Получаем vtbl сотоварищи, и лишаемся no-throw гарантии для swap. K>>>по сравнению с получеными удобствами не велика потеря. ЮЖ>>no-throw swap не велика потеря ? K>Для одинаковых классов no-throw выполняется,
Это я услышал слово "виртуальными" и подумал что предполагается полиморфная работа с контейнером.
K>к тому же обычно свап для векторов используют как move.
В присутствии no-throw swap относительно легко реализуется транзакционность и обеспечение strong guarantee при возникновении исключений.
ЮЖ>>А что в строках нужно кастомизировать ? Строки это вообще вещь такая... неоднозначная. каждому надо что-то свое кастомизировать. K>внутренний буфер, например, кастомизировать нельзя. может у меня все строки размером гораздо больше чем этот буффер и смысла в нем для меня нет.
Вот я о том и говорю: если кто-то не находит способа кастомизации "своего" аспекта в неком классе/библиотеке/etc., то начинают его ругать. Только вот всех аспектов не предусмотришь...
Здравствуйте, Erop, Вы писали:
E>>>Вообще в дизайне STL лично мне очень не нравится отсутсвие целенаправленности. Скажем вот добавили в контейнеры аллокаторы. При этом зачем это сделали не понятно. Ни возмоэность передать контейнеру конкретный пул памяти не предусмотрели, ни возможность гранулировать аллокации. Результат печальный -- аллокаторы есть, а толку нет. И так во многих очень местах J>>Ну, аллокаторы еще только ленивый не пнул. E>Проблема не в том, что они плохи, и не придумали хороших, а в том, что добавили в стандарт не пойми что не пойми зачем.
из стандарта:
...allocators, which are objects that encapsulate the information about an allocation model. This information includes the knowledge of pointer types, the type of their difference, the type of the size of objects in this allocation model, as well as the memory allocation and deallocation primitives for it.
Не знаю как в embedded, но в там где видел, их используют только в качестве "memory allocation and deallocation primitives", а предназначались они не только(far/near и т.п, что уже наверное является атавизмом) для этого.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Не знаю как в embedded, но в там где видел, их используют только в качестве "memory allocation and deallocation primitives", а предназначались они не только(far/near и т.п, что уже наверное является атавизмом) для этого.
А разве far/near стандартны? В любом случае не понятно почему и за что все экземпляторы аллокатора объявили эквивалентными...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Не знаю как в embedded, но в там где видел, их используют только в качестве "memory allocation and deallocation primitives", а предназначались они не только(far/near и т.п, что уже наверное является атавизмом) для этого.
E>А разве far/near стандартны?
Нет конечно, просто это вписывается в allocation model, о которой говорится в стандарте.
E>В любом случае не понятно почему и за что все экземпляторы аллокатора объявили эквивалентными...
С некоторой натяжкой они все же могут быть эквивалентными:
20.1.5
"Implementors are encouraged to supply libraries that can accept allocators that encapsulate more general
memory models and that support nonequal instances. In such implementations, any requirements imposed
on allocators by containers beyond those requirements that appear in Table 32, and the semantics of containers
and algorithms when allocator instances compare nonequal, are implementation-defined."
Тут вот какая проблема: если два объекта аллокатора равны(в терминах оператора ==), то из этого следует, что память выделенную одним объектом, можно освободить другим(20.1.5). А что делать контейнерам с различными объектами аллокаторов при присвоении, swap'ах и некоторых других операциях(list::splice) операциях ? Вариантов несколько: запретить, разрешить(и получить кидающий swap за O(N) с изменением гарантий по complexity связанных операций), либо изменить аллокаторы...
Другая проблема, не относящаяся к эквивалентности, в том что тип allocator<T>::pointer обязан быть T*. Т.е. какой-либо смарт-поинтер использовать нельзя.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Другая проблема, не относящаяся к эквивалентности, в том что тип allocator<T>::pointer обязан быть T*. Т.е. какой-либо смарт-поинтер использовать нельзя.
Ну это, хотя бы понятно, что могли и не предусмотреть.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Юрий Жмеренецкий, Вы писали: ЮЖ>С некоторой натяжкой они все же могут быть эквивалентными:
ОписАлся, должно быть: 'могут быть _не_ эквивалентными'
Здравствуйте, Kluev, Вы писали:
K>при небольшом числе элементов разницей можно пренебречь, но при увеличении их числа map начинает безнадежно отставать.
Это ты лукавишь.
При небольшом числе элементов хеш сливает стандартному мапу, у меня есть по крайней мере два таких случая в проекте, когда хеш (с хорошей хеш-функцией) работал хуже, чем std::map (с хорошей же операцией сравнения), и в моем случае этой разницей ну никак нельзя было пренебречь. (В случае большого числа элементов хеш выигрывал, но у меня не тот случай в этих двух конкретных местах)
Здравствуйте, jazzer, Вы писали:
J>При небольшом числе элементов хеш сливает стандартному мапу, у меня есть по крайней мере два таких случая в проекте, когда хеш (с хорошей хеш-функцией) работал хуже, чем std::map (с хорошей же операцией сравнения), и в моем случае этой разницей ну никак нельзя было пренебречь. (В случае большого числа элементов хеш выигрывал, но у меня не тот случай в этих двух конкретных местах)
А что за хэш? И по чём проигрывал? По памяти или по скорости?
По идее это как-то странно, что дерево эффективнее хэш-таблицы. Возможно, правда, у таблицы слишком дорогая инициализация, конечно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>При небольшом числе элементов хеш сливает стандартному мапу, у меня есть по крайней мере два таких случая в проекте, когда хеш (с хорошей хеш-функцией) работал хуже, чем std::map (с хорошей же операцией сравнения), и в моем случае этой разницей ну никак нельзя было пренебречь. (В случае большого числа элементов хеш выигрывал, но у меня не тот случай в этих двух конкретных местах)
E>А что за хэш? И по чём проигрывал? По памяти или по скорости? E>По идее это как-то странно, что дерево эффективнее хэш-таблицы. Возможно, правда, у таблицы слишком дорогая инициализация, конечно...
по скорости
Здравствуйте, jazzer, Вы писали:
E>>По идее это как-то странно, что дерево эффективнее хэш-таблицы. Возможно, правда, у таблицы слишком дорогая инициализация, конечно... J>по скорости
А реализация какая?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
E>>>По идее это как-то странно, что дерево эффективнее хэш-таблицы. Возможно, правда, у таблицы слишком дорогая инициализация, конечно... J>>по скорости E>А реализация какая?
разные пробовал, от STLPort до самописных и сгенеренных mph.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Kluev, Вы писали:
K>>чесно говоря я так и не понял для чего нужен этот класс, прочитав что это "многомерный массив" как-то пытался его использовать как двумерный массив, но так и не понял как в нем обратится к элементу по индексу [i,j].
J>через слайсы, или как они там называются.
прежде чем советовать попробывал бы сам. чтобы "удобство" оценить.
вот это: J>Если ты знаком с BLAS, то не должно быть проблем (я не знаком и с многомерными массивами по долгу службы не общаюсь).
очень плохо сочетается вот с этим: J>Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов.
Здравствуйте, Kluev, Вы писали:
K>>>чесно говоря я так и не понял для чего нужен этот класс, прочитав что это "многомерный массив" как-то пытался его использовать как двумерный массив, но так и не понял как в нем обратится к элементу по индексу [i,j].
J>>через слайсы, или как они там называются. K>прежде чем советовать попробывал бы сам. чтобы "удобство" оценить.
K>вот это: J>>Если ты знаком с BLAS, то не должно быть проблем (я не знаком и с многомерными массивами по долгу службы не общаюсь). K>очень плохо сочетается вот с этим: J>>Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов.
Что конкретно тебя смутило? Я не вижу противоречия. Или BLAS — это уже не скоростная библиотека?
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Kluev, Вы писали:
K>>при небольшом числе элементов разницей можно пренебречь, но при увеличении их числа map начинает безнадежно отставать.
J>Это ты лукавишь. J>При небольшом числе элементов хеш сливает стандартному мапу, у меня есть по крайней мере два таких случая в проекте, когда хеш (с хорошей хеш-функцией) работал хуже, чем std::map (с хорошей же операцией сравнения), и в моем случае этой разницей ну никак нельзя было пренебречь. (В случае большого числа элементов хеш выигрывал, но у меня не тот случай в этих двух конкретных местах)
свежо предание, но верится с трудом. хеш может сливать только в том случае когда хеш-функция дает много коллизий
или задан небольшой размер таблицы и много одинаковых значений hash%table_size. если у тебя отличная хеш функция — производителность достигается увеличением размера таблицы.
подбросив побольше памяти можно добится, что по каждому индексу hash%table_size будет сидеть один элемент. map должен быть совсем небольших размеров чтобы работать в этом случаее эффективнее hash. а на небольших размерах вместо map можно вполне обойтись отсортированным вектором.
Имхо, у тебя какая-то очень радкая и полумифическая ситуация если не подходят ни hash ни сортированный массив.
Здравствуйте, Kluev, Вы писали:
K>подбросив побольше памяти можно добится, что по каждому индексу hash%table_size будет сидеть один элемент. map должен быть совсем небольших размеров чтобы работать в этом случаее эффективнее hash. а на небольших размерах вместо map можно вполне обойтись отсортированным вектором. K>Имхо, у тебя какая-то очень радкая и полумифическая ситуация если не подходят ни hash ни сортированный массив.
Большую таблицу долго инициализировать...
Правда массив должен подходить для совсем маленьких коллекций...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, jazzer, Вы писали:
K>>вот это: J>>>Если ты знаком с BLAS, то не должно быть проблем (я не знаком и с многомерными массивами по долгу службы не общаюсь). K>>очень плохо сочетается вот с этим: J>>>Вообще-то этот самый "вектор значений, который я не помню как зовут" и есть многомерный массив, причем в лучших традициях скоростных библиотек этих самых массивов.
J>Что конкретно тебя смутило? Я не вижу противоречия. Или BLAS — это уже не скоростная библиотека?
смутило то, что ты берешься рассуждать о том с чем не работаешь.
Здравствуйте, Kluev, Вы писали:
K>смутило то, что ты берешься рассуждать о том с чем не работаешь.
Ты с этим тоже не работаешь, вроде как.
Я, по-моему, сразу же сказал, что в реальной работе его не использовал. Но что он сделан по образцу фортрановских ЛА-библиотек для векторных процессоров — это, вроде, факт, не зависящий от того, работал я с библиотекой или нет.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Kluev, Вы писали:
K>>смутило то, что ты берешься рассуждать о том с чем не работаешь.
J>Ты с этим тоже не работаешь, вроде как.
J>Я, по-моему, сразу же сказал, что в реальной работе его не использовал. Но что он сделан по образцу фортрановских ЛА-библиотек для векторных процессоров — это, вроде, факт, не зависящий от того, работал я с библиотекой или нет.
это еще ни о чем не говорит. ради интереса поискал в boost blas, упоминамний о valarray не нашел. зато в нем есть куча своих доморощенных массивов.
Здравствуйте, Kluev, Вы писали:
J>>Я, по-моему, сразу же сказал, что в реальной работе его не использовал. Но что он сделан по образцу фортрановских ЛА-библиотек для векторных процессоров — это, вроде, факт, не зависящий от того, работал я с библиотекой или нет.
K>это еще ни о чем не говорит. ради интереса поискал в boost blas, упоминамний о valarray не нашел. зато в нем есть куча своих доморощенных массивов.
Вот именно что ни о чем — boost blas и valarray не обязаны никак быть связанными. И факт их связанности или несвязанности никакого отношения к происхождению valarray не имеет.
Давай прекращать уже этот бессмысленный флейм с цеплянием к словам.