Какие библиотеки, функции и/или классы используются (ну или наиболее распространены в силу своей надежности, производительности, гибкости, компактности, простоты или чего-нибудь еще) для манипуляций такими динамическими объектами как строки, массивы, списки и т.п.?p.s.
Подразумеваются, естественно, объекты, которые сами занимаются выделением и освобождением памяти, снимая эту задачу с программиста.
>Какие библиотеки, функции и/или классы используются (ну или наиболее распространены в силу
>своей надежности, производительности, гибкости, компактности, простоты
>или чего-нибудь еще) для манипуляций
>такими динамическими объектами как строки, массивы, списки и т.п.?STL, однако. Вне конкуренции.
Кому не хватает - есть ещё Boost Libraries.
>STL, однако. Вне конкуренции.А как насчет получения указателей на буферы объектов STL? В описаниях предлагается использовать оператор []. Но ведь это ж медленно. Или я неправ?
Можно, правда, пытаться получать их &obj_name[0], но будет ли это корректным?
Например, будет ли корректным такой код?
// Здесь я взял кусок из примера и немного его переделал
vector<int> vec_one;
int a = 2; // Some integer data objects
int b = -5;vec_one.push_back(a); // Add item at end of vector
vec_one.push_back(9);
vec_one.push_back(b);
// vec_one now contains three int values: 2, 9, -5unsigned int i;
size_t sz = vec_one.size();
int *vec_buf = &vec_one[0];for (i = 0; i < sz; i++)
{
printf("%d\n", *vec_buf++);
}
// Вроде бы работает, но непонятно, будет ли такой
// способ работать при существенном увеличении
// кол-ва элементов в массивеЕсть ли более правильный способ быстрого доступа к буферам STL - объектов?
>>STL, однако. Вне конкуренции.
>
>А как насчет получения указателей на буферы объектов STL?
>В описаниях предлагается
>использовать оператор []. Но ведь это ж медленно. Или я неправ?При использовании нормальной реализации STL (сиречь в современных
условиях - нормального компилятора) - разница в скорости будет
несущественная. Оператор [] для вектора не выполняет проверок
корректности аргументов и его использование фактически
эквивалентно прямой работе с указателями.>
>Можно, правда, пытаться получать их &obj_name[0], но будет ли
>это корректным?Будет, но только до тех пор, пока состав элементов в контейнере
неизменен.>
>Например, будет ли корректным такой код?
>
>// Здесь я взял кусок из примера и немного его переделал
> vector<int> vec_one;
> int a = 2; // Some integer
>data objects
> int b = -5;
>
> vec_one.push_back(a); // Add item at end of vector
> vec_one.push_back(9);
> vec_one.push_back(b);
> // vec_one now contains three int values: 2, 9, -5
>
> unsigned int i;
> size_t sz = vec_one.size();
> int *vec_buf = &vec_one[0];
>
> for (i = 0; i < sz; i++)
> {
> printf("%d\n", *vec_buf++);
> }
>// Вроде бы работает, но непонятно, будет ли такой
>// способ работать при существенном увеличении
>// кол-ва элементов в массивеРаботать будет, но это ничем не отличается по скорости работы
от доступа через штатный оператор [].>Есть ли более правильный способ быстрого доступа к буферам STL -
>объектов?Буфера STL-объектов являются для них приватными, и попытки прямого
обращения к ним нарушают принцип инкапсуляции. Единственное исключение -
вектор, так как он (AFAIK) обязан хранить элементы в виде непрерывной
области памяти.
>При использовании нормальной реализации STL (сиречь в современных
>условиях - нормального компилятора) - разница в скорости будет
>несущественная.Ну, компилятор у меня, вероятно, не самый старый - gcc 3.3.6. Бог с ним. Интересно как этого добиваются? Казалось бы, при инкременте (ассемблерный оператор INC) не нужно ничего перезаписывать, циклически выполняется одна и та же операция над одним и тем же операндом, в то время как при сложении нужно изменять прибавляемый операнд.
Кстати, известно ли насколько несущественной будет разница?
>Оператор [] для вектора не выполняет проверок
>корректности аргументов и его использование фактически
>эквивалентно прямой работе с указателями.Да, но какой бы индекс не был указан, его нужно будет прибавить к адресу начала, ну и соответственно при инкременте индекса приходится его инкрементировать, а потом еще и прибавлять к адресу начала.
>Работать будет, но это ничем не отличается по скорости работы
>от доступа через штатный оператор [].Если инкрементирование быстрее сложения (в чем я не уверен, так как не гуру в программировании), то различие может быть существенным. Пороком приведенного кода является параллельное инкрементирование счетчика цикла, что во многих задачах не нужно. Можно было бы предположить различие и в случае если кол-во инкрементируемых указателей в одном цикле (с одним лишь счетчиком) достаточно велико (время инкрементирования самого счетчика будет составлять незначительную часть).
>Буфера STL-объектов являются для них приватными, и попытки прямого
>обращения к ним нарушают принцип инкапсуляции. Единственное исключение -
>вектор, так как он (AFAIK) обязан хранить элементы в виде непрерывной
>области памяти.А на строки принцип непрерывности не распространяется?
>>При использовании нормальной реализации STL (сиречь в современных
>>условиях - нормального компилятора) - разница в скорости будет
>>несущественная.Кстати, я тут несколько продвинулся по чтению доки от stl и добрался до "итераторов". Хоть непосредственно в документации и нет прямых примеров, легко догадаться, что приведенный код можно легко мдифицировать, заменив указатель итератором (собственно, это и есть ответ на мой же вопрос, т.к. все операции поддерживаются и документированы в stl в отличие от операций предыдущего кода):
vector<int> vec_one;
int a = 2; // Some integer data objects
int b = -5;vec_one.push_back(a); // Add item at end of vector
vec_one.push_back(9);
vec_one.push_back(b);
// vec_one now contains three int values: 2, 9, -5unsigned int i;
size_t sz = vec_one.size();vector<int>::iterator iter = vec_one.begin();
//int *vec_buf = &vec_one[0];for (i = 0; i < sz; i++)
{
// не будем использовать
// printf("%d\n", *vec_buf++);
// пока я не нашел в доке указаний на гарантию непрерывности
// а будем делать так:printf("%d\n", *iter++);
}Не уверен, конечно, но такой код легко может компилироваться как простое инкрементирование адреса, что собственно и нужно.
Не сочтите за укор, но мне сдаётся, что вы пытаетесь прыгнуть выше головы. Пытаетесь оптимизировать некий потенциальный код, не зная толком, что выдаёт компилятор и как с этим работает процессор. И даже не ознакомившись предварительно с рекомендациями авторов STL по использованию оной.
Мне кажется, что STL и её реализации (например, от GNU) писали неглупые люди. И что лучше потратить время на изучение инструмента, чем охотиться за призраками.
К тому же оптимизация хороша в контексте, а абстрактно она не имеет никакого смысла. Например, если в некоем цикле имеет место обращение к элементам массива (или вектора, или ещё какого-нибудь контейнера) и при этом в каждой итерации делается пара вызовов и ещё чего-нибудь там, то парой инструкций больше, парой меньше - уже не играет никакой роли.
А обращение к приватным данным класса напрямую представляется мне одной из самых плохих идей, которые можно вообразить. Какой смысл тогда в использовании классов? Только ради автоматического освобожюдения памяти после использования? Тогда уж лучше написать свой класс, если STL не устраивает. Но что-то мне подсказывает, что в этом случае вы не получите ничего, кроме потенциальных проблем сразу или в будущем. (То есть, я не хочу, конечно, сказать, что своих классов писать вообще не надо. Но для тех целей, которые вы описываете, стандартных классов должно быть вполне достаточно. Главное - научиться ими пользоваться)Что-то длинно получилось. Ещё раз, не сочтите за наезд - это просто добрый совет и просто моё мнение.
>Не сочтите за укор, но мне сдаётся, что вы пытаетесь прыгнуть выше
>головы.Часто это бывает полезным - тело вытягивается ;)
> Пытаетесь оптимизировать некий потенциальный код, не зная толком, что выдаёт
>компилятор и как с этим работает процессор. И даже не ознакомившись
>предварительно с рекомендациями авторов STL по использованию оной.Нет. Не совсем так. Код - не совсем потенциальный. Честно говоря, в спешке я написал некоторые функции на основе malloc, которые заменяли в программе использование стандартных контейнеров, и они надежно работают (нет утечек). Но уже тогда, когда я все это писал я знал о существовании стандартных функций, и вот теперь, когда появилась следующая задача, и я примерно представляю как ее решать, я хочу пользоваться более стройными и выверенными решениями тех самых "неглупых" людей о которых вы и пишете. И сделать это _в соответствии с рекомендациями_.
>Мне кажется, что STL и её реализации (например, от GNU) писали неглупые
>люди. И что лучше потратить время на изучение инструмента, чем охотиться
>за призраками.Что я и делаю. Если вы помните, то в начале темы я вообще не знал как называется этот инструмент.
>К тому же оптимизация хороша в контексте, а абстрактно она не имеет
Контекст есть, но обсуждать его в этой теме нет необходимости.
>А обращение к приватным данным класса напрямую представляется мне одной из самых
>плохих идей, которые можно вообразить. Какой смысл тогда в использовании классов?Собственно, ответ на вопрос, как избежать некорректного обращения к приватным данным я и пытался получить.
Использование шаблона STL iterator и есть рекомендация авторов (См. кусок кода в предыдущем сообщении. Обратите внимание на то, что прямого обращения к приватному куску объекта там нет). Кстати, если вы уже давно знакомы с STL и широко ее используете, то возможно, вам будет интересно освежить в памяти раздел про итераторы, про то, какими они бывают и в каких случаях используются. Лично я понимаю их необходимость, как шаблонов для замены указателей, предназначенных, в том числе, для быстрого перебора.
>Только ради автоматического освобожюдения памяти после использования? Тогда уж лучше написать
>свой класс, если STL не устраивает. Но что-то мне подсказывает, что
>в этом случае вы не получите ничего, кроме потенциальных проблем сразу
>или в будущем. (То есть, я не хочу, конечно, сказать, что
>своих классов писать вообще не надо. Но для тех целей, которые
>вы описываете, стандартных классов должно быть вполне достаточно. Главное - научиться
>ими пользоваться)Не стоит рассматривать приведенные куски кода как цель или контекст.
Я и не описывал никаких целей. Интересовался лишь возможностью замены указателей (ну или в вашей терминологии - рекомендациями), но ответ я нашел как раз в документации, хотя мог бы получить его и здесь, если нашелся бы человек, который точно его знал.
>Я и не описывал никаких целей. Интересовался лишь возможностью замены указателей (ну
>или в вашей терминологии - рекомендациями), но ответ я нашел как
>раз в документации, хотя мог бы получить его и здесь, если
>нашелся бы человек, который точно его знал.Уверяю вас, про итераторы (и "какими они бывают и в каких случаях используются") знают все, кто более-менее знаком с C++ и STL. Просто из-за неточной формулировки вопроса было не совсем ясно, что же именно вам нужно.
По C++ вообще и по STL в частности рекомендую почитать создателя языка, а именно книгу "Язык программирования C++", Б. Страуструп.