С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
1

О деталях и возможностях реализации <vector>

06.04.2016, 04:17. Показов 2572. Ответов 82
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
 Комментарий модератора 
Эта тема выделена из темы: Работа с векторами без использования STL и библиотеки <vector>


Цитата Сообщение от hoggy Посмотреть сообщение
если он не будет защищен внутренними проверками.
я б такую халтуру вообще бы не принял.
Ну это уже в зависимости от зависимости. Примерно в 50% случаев внутренняя проверка только дает оверхед.
из кода AnsiString (той которая в комплекте C++ Builder)
C++
1
2
3
4
5
char operator [](const int idx) const
    {
      ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
      return Data[idx];
   }
Так и сидит в инклюде который идет в поставке с таким комментарием.
в подавляющем большинстве случаев разумно вот так:
C++
1
2
3
4
5
6
7
char operator [](const int idx) const
    {
#ifdef __DEBUG__
      ThrowIfOutOfRange(idx);
#endif
      return Data[idx];
   }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.04.2016, 04:17
Ответы с готовыми решениями:

О возможностях реализации поставленных задач
Здравствуйте уважаемые форумчане. На работе встала задача написать программу, которая из одной...

Скрыть <iostream> в деталях реализации
Здравствуйте, необходимо переместить #include &lt;iostream&gt; из .h в .cpp, и при этом использовать...

Программа для реализации арифметических операций Matrix, Vector
Помогите написать программу, для реализации арифметических операций классов Matrix, Vector.Спасибо...

Написать шаблон класса на основе класса vector для реализации стековой структуры данных
Пыталась написать код, но не уверена будет ли такая реализация корректной, можно ли это сделать...

82
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 03:34  [ТС] 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
никто в здравом уме не выпиливает исключения в релизе,
и не делает отказоустойчивый код бесполезным хламом.
Если код не в состоянии вычислять границы массивов к которым он обращается он не то что неотказоустойчивый, он нерабочий. Екскепшены в этом плане предоставляют огромные удобства по вылову таких ошибок. А вот когда он надежно вычисляет границы извне, то и никакие внутренние проверки становятся не нужны.
Цитата Сообщение от hoggy Посмотреть сообщение
он укажет точное место, где сработал.
программист может заложить дополнительную текстовую информацию.
В том числе по всем вышестоящим функциям?

Добавлено через 4 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
допустим, его пользователь в консольке вводит. мало ли чего он там введет
Проверять надо что пользователь в консольке вводит. А еще лучше не в консольке давать индексы элементов указывать а мышкой выбирать из существующих.
Цитата Сообщение от Renji Посмотреть сообщение
Если "назначай сам", то откройте для себя метод reserve.
И вызывать его на каждом шагу? Я свойство Capacity для себя как то не закрывал. Но с GrowStep достаточно один раз указать шаг, при потребности рост с таким резервом.

Добавлено через 2 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
в вашем же случае становится не очевидно:
на бою эта защита сработает, или нет?
В моем случае в бою она не нужна. Потому что в учении добились что такая пакость у супостата не пройдет.

Добавлено через 2 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
такое делают в условиях,
когда исключительным ситуациям априори имеет место быть.
Кто запрещает пользоваться теми же методами для дебага если они удобны?

Добавлено через 1 минуту
Цитата Сообщение от hoggy Посмотреть сообщение
например, он ловит исключение,
и вывешивает табличку "повторите свой запрос позже"
В этом случае throw используется фактически как return через несколько уровней вложенности вызовов, именно в то место где ждут результат. Тоже удобное применение. Но не единственное.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
07.04.2016, 03:54 22
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Но с GrowStep достаточно один раз указать шаг, при потребности рост с таким резервом.
Если "один раз указать шаг", будет квадратичная сложность алгоритма вставки N элементов. На N вставок n/GrowStep реаллоков, каждый следующий тормозит на GrowStep единиц времени больше (потому что весь массив перемещается в новое место). То есть, суммарные тормоза - сумма арифметической прогрессии, растущая пропорционально квадрату N.
Так я еще раз повторяю, константное амортизированное (суммарное время пиханий/число пиханий) время ваш велосипед гарантирует?
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если код не в состоянии вычислять границы массивов к которым он обращается он не то что неотказоустойчивый, он нерабочий.
В состоянии. Просто, стандартная реакция на некорректные входные данные - аварийное завершение алгоритма и цепочка return до обработчика ошибок. Так какая собственно, разница из какого места эта цепочка начнется?
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
В том числе по всем вышестоящим функциям?
М... Вы отладчиком пользоваться пробовали? Да, он покажет весь стек вышестоящих функций. Если же предлагается запускать дебаг-сборку на удаленной машине без отладчика, так это сексуальное извращение.
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 05:55  [ТС] 23
Цитата Сообщение от Renji Посмотреть сообщение
М... Вы отладчиком пользоваться пробовали?
Правильно. Вот по trow он и останавливается на сбойной итерации. Переходишь вверх по стеку вызовов и смотришь значения всех переменных при которых произошел сбой. А не трассируешь до посинения. Фактически используется как debug echo с автоматически установленной на него точкой останова.
Цитата Сообщение от Renji Посмотреть сообщение
один раз указать шаг
Размер шага при этом может очень даже зависеть от количества вставок за один присест, и указываться для каждого конкретного массива в любое время. При этом на малых последовательностях только одно распределение, а при стратегии вектора именно на малых последовательностях будет постоянный реалок с копированием. При большом количестве таких малых последовательностей тормоза у std::vector гарантированы если через reserve не имитировать GrowStep. На больших же последовательностях std::vector будет оверхед по памяти, причем чем больше последовательность тем этот оверхед выше. Управление размером роста такая штука что не угадаешь на все случаи жизни как размер прироста делать. А тем более если еще и при удалении автоматически размер уменьшать. Для более-менее универсальной стратегии подходит только страничное распределение, но и оно только при очень интенсивных добавлениях/удалениях в/из начало/конец последовательности оправдано, иначе будет сравнимо с умным использованием Capacity и GrowStep. Опять же учитывая что в подавляющем большинстве случаев сами динамические массивы хранят списки указателей на объекты то копируется при ресайзе не такой уж и большой объем данных. Ну а при рандомной вставке/удалении все равно не сравнимо со временем затрачиваемым на сдвиг последовательности, мало того сдвиг может быть совмещен с копированием при ресайзе.

Добавлено через 3 минуты
Цитата Сообщение от Renji Посмотреть сообщение
В состоянии. Просто, стандартная реакция на некорректные входные данные - аварийное завершение алгоритма и цепочка return до обработчика ошибок
Если код сгенерировал некорректные входные данные для нижестоящего кода, то это нерабочий код.

Добавлено через 19 минут
Цитата Сообщение от hoggy Посмотреть сообщение
вы не правильно используете механизм эксепшенов.
такое впечатление, что вы не понимаете,
зачем он вообще на самом деле нужен.
Начнем с того зачем и как его использовать и зачем он нужен решать только мне в каждом конкретном случае, а не какому то комитету или еще кому то. К примеру как то использовал exception для возврата результата из рекурсивной функции поиска. И все прекрасно.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
07.04.2016, 06:06 24
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Правильно. Вот по trow он и останавливается на сбойной итерации.
По throw он вообще не останавливается. Исключение прилетает в catch секцию, catch секция плюется сообщением "извините, не взлетело. Причина - error.what()" и программа пашет дальше. Или настоящие индейцы обработчики исключений не пишут?
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Размер шага при этом может очень даже зависеть от количества вставок за один присест, и указываться для каждого конкретного массива в любое время.
Вы определитесь - мы указываем шаг "в любое время" или один раз? И мы что оптимизируем, среднее время вставки или время вставки в небольшие массивы? Потому как второе делается совсем иначе.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class myVector
{
public:
    //пока массив маленький, дорогое обращение к динамической памяти вообще не используется
    void push_back(int value){
        if(size==capacity)
        {
            capacity*=2;
            int*newData=(int*)malloc(sizeof(int)*capacity);
            memcpy(newData,data,sizeof(int)*size);
            data=newData;
        }
        data[size++]=value;
    }
    int operator[](int pos)const{return data[pos];}
 
private:
    int buf[16];
    int*data=buf;
    int size=0;
    int capacity=16;
};
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если код сгенерировал некорректные входные данные для нижестоящего кода, то это нерабочий код.
Некорректные данные сгенерировал пользователь. А код только плюнул в ответ исключением с диагностическим сообщением, описывающим произошедшее в меру лени кодера.
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 07:04  [ТС] 25
Цитата Сообщение от hoggy Посмотреть сообщение
сказал человек, который не осилил stl.
Не пробовали по другому вопрос ставить - stl не осилила мои потребности ни к контейнерам, ни к делегатам,ни к свойствам, ни к RTTI. Ну слава богу руки вроде не кривые чтобы своими контейнерами обзавестись и в случае необходимости расширять номенклатуру оных, ну а на все остальное борланд есть, да и контейнеры у борланда тоже очень даже ничего, массивы конечно не совсем айс, вынужденный аналог паскалевских, но вот строки и списки это нечто. НУ а двумерные и т.д. массивы по оперделению свои. Их ни в одном комплекте нет.

P.S.: да кстати, похоже STL вообще ничьи потребности не осилила, потому как не встречал использования оной ни в коде от Борланда (хотя на борту лежит в версии Dinkumware), ни в коде от Майкрософт (хотя на борту в своей патентованной версии, работающей местами через расширения синтаксиса), ну если где то и проскакивает у мелкомягких, то по мелочи на задворках. А вся основная работа работается лисапетами как вы их называете.

Добавлено через 1 минуту
Цитата Сообщение от Renji Посмотреть сообщение
И мы что оптимизируем, среднее время вставки или время вставки в небольшие массивы?
Вот в том то и дело что нельзя оптимизировать все и сразу.

Добавлено через 32 минуты
Цитата Сообщение от Renji Посмотреть сообщение
Потому как второе делается совсем иначе
"Обалденный" способ. Особенно счастливы от него будут те кому при помощи этих векторов нужно будет организовывать связность деревьев, у которых в любой момент времени у подавляющего большинства элементов эти вектора нижестоящих узлов пустые.

Добавлено через 6 минут
Цитата Сообщение от Renji Посмотреть сообщение
А код только плюнул в ответ исключением с диагностическим сообщением, описывающим произошедшее в меру лени кодера
Ну ежели в хеллоувердах то может и так. А ежели в софте то как бы может в ответ не диагностическим сообщением плюнуть а к примеру сотней тонн жидкой стали.

Добавлено через 8 минут
P.S.: про оптимизацию я это к тому что на все случаи жизни не угадаешь, поелику оптимизация по одному признаку, нужная в одном конкретном случае зачатую противоречит оптимизации нужной в другом конкретном случае. Поэтому что бы там коммитет в плане какой либо библиотеки не пытался стандартизировать, лисапетили и лисапетить будут, и правильно делают. А те кто это еще неосилили и есть неосилянты.

Добавлено через 9 минут
Цитата Сообщение от hoggy Посмотреть сообщение
штатная обработка ошибок пользователя.
А разве надпрограмма не является пользователем подпрограммы? Вот ее ошибки светятся и штатным образом дебагятся при помощи екскепшинов.
Ну а если так смотреть, то два наиболее эффективных способы отладки это трассировка с точками останова и debug echo. И сколько не холиварили на тему что из этих спсобов лучше, то и тот и тот имеет свои как огромные плюсы так и нехватку плюсов второго способа. А соостветсвенно те кто при мозгах всегда пытались два эти способа комбинировать, с самой зари компьютерных технологий. Так вот throw это по большому счету кроме всего остального еще и debug echo с автоматически установленной на него под дебаггером точкой останова - т.е. мощнейший инструмент отладки о котором мечтали во все времена. И не использовать его просто глупо.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
07.04.2016, 07:13 26
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
"Обалденный" способ. Особенно счастливы от него будут те кому при помощи этих векторов нужно будет организовывать связность деревьев, у которых в любой момент времени у подавляющего количества элементов эти вектора нижестоящих узлов пустые.
Таки да, будут счастливы. Потому как выделение динамической памяти под эти вектора скушает тактов этак сто, а то и всю тысячу. И за это время можно десять раз завершить инициализацию собственно узла дерева. В Виларибо уже праздник, а жители Вилабаджо все еще ждут завершения выделения памяти под вектор.

Вы определитесь, вам экономию памяти или быструю работу? Потому как и то, и то разом не бывает.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
P.S.: про оптимизацию я это к тому что на все случаи жизни не угадаешь, поелику оптимизация по одному признаку, нужная в одном конкретном случае зачатую противоречит оптимизации нужной в другом конкретном случае.
Поелику оптимизируют амортизированное время, гарантируя что среднее время вставки будет оставаться константой. Причем, без какого либо тамогочения шагов А вот как достигнуть того же самого с вашим настраиваемым шагом я пока не увидел.
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 10:59  [ТС] 27
Цитата Сообщение от Renji Посмотреть сообщение
Потому как выделение динамической памяти под эти вектора скушает тактов этак сто, а то и всю тысячу
Ага. Только на каждый нод ее все равно выделять. А вот с таким подходом как у вас жители Виларибо будут ждать выделения места на винте гораздо дольше чем жители Вилобаджо выделят буфера только там где они необходимы. Да кстати, ООП программы как раз обычно очень очень большим количеством подобных узлов деревьев оперируют. И увеличивать им количество элементов пропорционально уже существующим в списке тоже вредно, а особенно умножать на 2. Потому как объекты имеют свойство генерироваться по командам пользователя либо по одному либо в известном до вставки количестве на одну генерацию. При десериализации размер тем более известен заранее (во всяком случае при толково разработанном формате файла).
Цитата Сообщение от Renji Посмотреть сообщение
Поелику оптимизируют амортизированное время, гарантируя что среднее время вставки будет оставаться константой
Не будет. Так как очень быстро память начнет не в RAM а на HDD выделяться. Оверхед по размеру скушает все преимущества от пропорционального увеличения размера. Да кстати при добавлении удалении только в начало/конец с кольцевым буфером (гораздо более актуально чем вектора для организации всяких очередей и т.п.) или с массивом со страничной организацией памяти (актуальны на больших последовательностях) они тоже никогда по скорости не сравнятся. Ну а при рандомной вставке удалении ни о каком константном времени говорить не приходится. Оно только у деков константным может быть в таком случае, да и то при указании не номера а адреса элемента перед которым вставлять.
Ну а для относительно небольших последовательностей, особенно которые занимаются преимущественно накоплением связей (подавляющее большинство случаев использования динамических массивов) таки получается c GrowStep оптимальней. Хотя опять же. Многое зависит:
Цитата Сообщение от Renji Посмотреть сообщение
Поелику оптимизируют амортизированное время
От того что считать временем. Поелику если есть понятие таймфрейм, то лучше замерять приход элементов в течение таймфрейма и поставить GrowStep большим чем этот приход, чтобы гарантировать не более одного реалока в течение таймфрейма, и при этом минимизировать оверхед по памяти,что особо актуально если данные в конце таймфрейма вытесняются на диск осью (меньше время выгрузки в конце таймфрейма и подгрузки в начале). При этом исключаются просадки в отдельно взятых таймфреймах (просадки плохи тем что снижают точность определения запаса вычислительной мощности). Опять же если пользуются несколько массивов то пусть лучше каждый реалочится в каждом таймфрейме, зато гарантированно виден запас вычислительной мощности, чем совпадет реалок нескольких (достаточно редкое явление) в одном таймфрейме и оного запаса не хватит. Рандомные лаги в игрухах видели? Очень часто причина именно в совпадении реалоков нескольких векторов в одном таймфрейме при недостаточном запасе вычислительной мощности. В игрухе поматерились по поводу разбившегося из за этого самолета и будет. А в реале?
Но вообще при таких раскладах более оптимальна страничная организация, с задаваемым размером станицы, а обычный массив с GrowStep пользуется для хранения адресов страниц.
Вообще реалтаймовые алгоритмы местами сильно отличаются от нереалтаймовых. Хотя бы тем что необходимо оптимизировать не общее время а гарантированно уложится в каждый тамфрейм, причем очень желательно с небольшой разницей между отдельно взятыми таймфреймами.

Добавлено через 53 минуты
Цитата Сообщение от avgoor Посмотреть сообщение
А как по вашему выделяется память при превышении capacity? По одному элементу, что ли?
Как-как. Выделяется новый кусок побольше. В него все копируется. Потом старое удаляется.
А страничная организация - массив страниц по 2^k элементов в каждой странице. Нужно увеличить размер - выделили еще страницу, добавили ее в массив страниц. а в operator [] выбираем элемент как
Data[Id>>k][Id&((1<<k)-1)]; Рост вообще очень быстрый. Причем как спереди так и сзади. Ужатие тоже. Но как видите есть небольшой оверхед при доступе.

Добавлено через 54 минуты
Цитата Сообщение от Renji Посмотреть сообщение
По throw он вообще не останавливается
Выбросьте свой дебаггер. На что мелкомягкий убитый в этом плане, но и тот останавливается, хотя и где то на 2 вызова глубже. Борландовский прямо на этот trow становится. И в обоих дебагерах можно подняться вверх по стеку вызовов посмотреть какие значения у переменных из которых индекс вычислялся (ну или вообще данные которые привели к сбою). Ну а если пустить дальше, то да, пойдет выходить из всего и вся до ловушки.

Добавлено через 5 минут
Цитата Сообщение от Renji Посмотреть сообщение
Вы определитесь, вам экономию памяти или быструю работу? Потому как и то, и то разом не бывает
Бывает. Только разработчики STL об этом ни разу не в курсе.

Добавлено через 11 минут
Хотя дело даже не в том что надо определится по чем оптимизировать. Главный вопрос в том что универсально подходящей везде оптимизации быть просто не может. Для примеру: тому же массиву со страничной организацией для выполнения своих внутренних операций нужен массив с копированием при ресайзе. При этом к примеру локальному массиву (для промежуточных данных) живущему внутри метода, вполне возможно и важно быстрое наращивание количества элементов. А вот долгоживущему массиву-полю, хранящему связи объекта, таки важна оптимизация по памяти и скорости доступа.

Добавлено через 13 минут
При этом в большинстве случаев добавление будет в рандомную позицию, а не в конец, т.к. всем известно что неупорядоченные связи ведут к std (sexually transmitted disease - заболевания передаваемые половым путем (толковый словарь английского языка).
0
1550 / 875 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
07.04.2016, 12:53 28
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Выбросьте свой дебаггер. На что мелкомягкий убитый в этом плане, но и тот останавливается
С чего бы вдруг ему останавливаться на обработанном исключении. Вы сами писали:
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
К примеру как то использовал exception для возврата результата из рекурсивной функции поиска
Дебагер должен останавливаться не каждом штатном вызове?
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 14:10  [ТС] 29
Цитата Сообщение от avgoor Посмотреть сообщение
С чего бы вдруг ему останавливаться на обработанном исключении. Вы сами писали:
С того что он дебаггер. Работа у него такая - на точках останова и экскепшинах останавливаться.
Цитата Сообщение от avgoor Посмотреть сообщение
Дебагер должен останавливаться не каждом штатном вызове?
На экскепшине останавливается. Если так и задуманно можно запустить дальше или даже пометить что дебагеру по этому типу экскепшинов не останавливаться. В том то и дело что экскепшен это пригодная к обработке нештатная ситуация

Добавлено через 12 минут
И останавливается он не в месте обработки а в месте выброски. т.е. оно на этот момент времени еще свежее и необработанное и даже не передавшее управление из того места где выброшено.
0
1550 / 875 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
07.04.2016, 14:14 30
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если так и задуманно можно запустить дальше или даже пометить что дебагеру по этому типу экскепшинов не останавливаться.
Вот нахрена это нужно, если есть assert - специальный инструмент для отладки?

Если ваш дебагер остановится здесь:
C++
1
2
3
4
5
6
try {
    throw std::exception();
}
catch (std::exception e) {
    std::cerr << "blablabla" << std::endl;
}
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Выбросьте свой дебаггер.
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 14:25  [ТС] 31
Цитата Сообщение от avgoor Посмотреть сообщение
если есть assert - специальный инструмент для отладки?
Давно устаревший. Как минимум 20 лет.
Цитата Сообщение от avgoor Посмотреть сообщение
Если ваш дебагер остановится здесь:
С++ Builder остановится в строке 2, MSVC на пару вызовов из строки 2 глубже. Естественно при запуске через Debug Kernel из IDE. При запуске без Debug Kernel никаких остановок естественно не будет.

Добавлено через 5 минут
Цитата Сообщение от avgoor Посмотреть сообщение
Вот нахрена это нужно
Для того чтобы увидеть не только номер строчки в которой мы узнали об ошибке, но и всю трассу которая к этой ошибке привела и в т.ч. объект в котором она возникла.
0
1550 / 875 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
07.04.2016, 14:26 32
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Естественно при запуске через Debug Kernel из IDE
Мсье знает толк.
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
07.04.2016, 14:33  [ТС] 33
Цитата Сообщение от avgoor Посмотреть сообщение
Мсье знает толк.
А вы что хотите их по записям в черных ящиках отлаживать? Так это слишком дорого да и черные ящики далеко не всегда находят.
Вообще бывают два вида нештатных ситуаций - не связанные с алгоритмом разрабатываемой программы (т.е. отсутствие файла, отсутствие связи по сети и т.п.) и связанные непосредственно с алгоритмом - т.е. вылет за пределы массивов, обращение по висящим указателям и т.п. Пока возникают экскепшины по второму виду ни о какой работоспособности кода говорить нельзя, а значит нельзя и запускать его в продакшн. А вот в отладке именно этих ошибок остановка по экскепшинам очень здорово помогает.
0
1550 / 875 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
07.04.2016, 14:41 34
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Для того чтобы увидеть не только номер строчки в которой мы узнали об ошибке
И? Посмотрите стек вызовов.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Пока возникают экскепшины по второму виду ни о какой работоспособности кода говорить нельзя,
А когда они уже не возникают (в продакшене), никаких throw не должно быть. Так assert и работает. Этим:
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
C++
1
2
3
#ifdef __DEBUG__ 
    ThrowIfOutOfRange(idx);
#endif
C++
1
 
вы просто навелосипедили свою, не побоюсь этого слова, убогую реализацию assert
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
07.04.2016, 17:50 35
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Ага. Только на каждый нод ее все равно выделять. А вот с таким подходом как у вас жители Виларибо будут ждать выделения места на винте гораздо дольше чем жители Вилобаджо выделят буфера только там где они необходимы.
У вас там все еще эпоха "640 килобайт хватит всем"? Еще одна планочка памяти на 16 гигабайт в Виларибо, обойдется куда дешевле нового процессора в Вилабаджо.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Опять же если пользуются несколько массивов то пусть лучше каждый реалочится в каждом таймфрейме, зато гарантированно виден запас вычислительной мощности
Еще раз, для тех кто в танке - реалок тормозит пропорционально размеру массива. То есть, при должном размере массива сожрет любые "запасы вычислительной мощности" и добавки попросит. Поэтому, оптимизировать можно только среднее время работы. Ну или пилить вектор заточенный под строго определенные размеры.
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.04.2016, 18:45 36
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Не пробовали по другому вопрос ставить - stl не осилила мои потребности ни к контейнерам, ни к делегатам,ни к свойствам, ни к RTTI.
пробовал. это не ваш случай.

я мог бы понять позицию человека, который сказал бы:
я знаю stl, просто мне он не нравится.

но ваша позиция: не знаю, и знать не хочу.
это - позиция неосилятора.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
ни в коде от Майкрософт
они не занимаются велосипедированием стандартной библиотеки
(которую сами же и изготовили).

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Если код не в состоянии вычислять границы массивов к которым он обращается он не то что неотказоустойчивый, он нерабочий. Екскепшены в этом плане предоставляют огромные удобства по вылову таких ошибок. А вот когда он надежно вычисляет границы извне, то и никакие внутренние проверки становятся не нужны.
это не имеет никакого отношения к эксепшен-бреду,
который вы постулируете.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
В том числе по всем вышестоящим функциям?
специально для вас выше написал:
тоже самое, что и с эксепшенами.
любая моральная иде покажет стек вызовов.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
А разве надпрограмма не является пользователем подпрограммы?
нет.

вы похоже так и не поняли.

вот вам пример:

C++
1
2
3
4
container ar[3] = {1,2,3};
for(size_t n=0;n<=3;++n)  //<--- выход за пределы диапазона
    foo(ar[n]);         // такого быть не должно в принципе,
                            // в корректной программе
другая ситуация:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
container ar[3] = {1,2,3};
 
size_t index;
for(;;)
{
    try{
        cin >> index;
        foo(ar.at(n));
        break;
    }
    catch(std::out_of_range&)
    {
        cout << "вы ввели корявый индекс\n"
           "попробуйте ещё раз\n";
    }
}
в первом случае ассерт выступает гарантией
корректности вызывающей стороны.

в дебаге он проконтролирует, что то,
чего не должно быть - не будет.

во втором случае - эксепшен.
пользователь может ввести все что угодно.

самолет не должен упасть и разбиться,
только потому, что пилот нажал не на ту кнопку.

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

вот именно для того, что бы вызывающая сторона
могла реализовать сценарий восстановления после некорректных данных,
и был создан механизм исключений.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Так вот throw это по большому счету кроме всего остального еще и debug echo с автоматически установленной на него под дебаггером точкой останова
не предназначен для отладки.
он предназначен для отказоустойчивости.

выше я задал вам вопрос,
на который вы мне так и не дали морального ответа.

рассмотрим пример:

C++
1
2
3
4
5
6
some::~some()
{
    const auto name = m_vector[0]; //<--- это ваш недо-вектор,
                          //который кидается эксепшенами
    close(name);
}
ничего аморального не наблюдаете?

я спрошу вас ещё раз:
вы ловушки тоже под дебажные дефаны закатываете?
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
08.04.2016, 04:00  [ТС] 37
Цитата Сообщение от hoggy Посмотреть сообщение
я знаю stl, просто мне он не нравится.
Она появилась гораздо позже чем более продвинутые средства. Зачем мне лезть в дебри малочитабельного говнокода который не имеет средств для решения необходимых мне задач?

Добавлено через 1 минуту
Цитата Сообщение от hoggy Посмотреть сообщение
самолет не должен упасть и разбиться,
только потому, что пилот нажал не на ту кнопку.
Представьте что в самолете вообще нет пилота. Но от этого абсолютно ничего не меняется.

Добавлено через 8 минут
Цитата Сообщение от hoggy Посмотреть сообщение
другая ситуация:
А вот это не очень хорошая практика. Потому как во первых ввод надо проверять, вне зависимости есть ли внутренние проверки внутри компонентов-вычислителей. Во вторых проверки для рандомного доступа дают ужасный оверхед при последовательном, при этом и рандомный в большинстве случаев имеет групповую внешнюю проверку.
Пример:
C++
1
2
3
4
5
TArray a<int>;
a,Count=50
for (int i=0;i<70;i++) {
      a[Random(a.Count-1)]=Random(500);
};
тут тоже дополнительные внутренние проверки только дают оверхед.
Соответсвенно, проверки включены на стадии отладки, только для того чтобы отладить корректность вычисления входных данных.
Опять же. Если входные данные не вводятся непосредственно а как либо вычисляемы, что и есть в подавляющем большинстве случаев, то екскепшен ну ничего хорошего тоже не сулит. Ассерт тем более. Так или иначе аварийное завершение всей программы при ассерте, или как минимум какой либо ее ветки вычислений при екскепшине. Результат тот же - птичка на земле.

Добавлено через 49 минут
Цитата Сообщение от hoggy Посмотреть сообщение
не предназначен для отладки.
Если вы не умеете использовать его для отладки то это не значит что он для этого не предназначен.
Цитата Сообщение от hoggy Посмотреть сообщение
он предназначен для отказоустойчивости.
Основа отказоустойчивости в корректности работы программ. trow это еще и инструмент который способен сообщить о некорректности программы на этапе отладки. В корректной программе возникновение таких экскепшинов исключено, в следствие невозможности срабатывания проверок их выбрасывающих.
Соответсвенно в релизе все эти проверки выпиливаются.

Добавлено через 4 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
ничего аморального не наблюдаете?
Поясните что делает ваш close, и что вы видите аморального?

Добавлено через 5 минут
Цитата Сообщение от hoggy Посмотреть сообщение
вы ловушки тоже под дебажные дефаны закатываете?
В большинстве случаев ловушка одна в самом верху. В остальном же ловушки как обычно - на открытии файлов, инициализации сетевых коннекций, и т.п, т.е. там где exception используется как возврат результата обращения к стороннему коду.
А те екскепшины которые по выходу за границы массива и т.п. вообще предназначены исключительно для ловли их дебаггером. Потому что никакая осмысленная обработка таких ситуаций кроме изменения кода программы невозможна.

Добавлено через 9 минут
Цитата Сообщение от hoggy Посмотреть сообщение
они не занимаются велосипедированием стандартной библиотеки
Посмотрите в код хотя бы тех же экземплов в составе DirectX. Упоминания stl:: есть три раза где то на задворках вспомогательного кода. А в основной работе пользуются более другие средства. Например CGrowableArray вместо std::vector

Добавлено через 3 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
у вызывающей стороны должна быть возможность
реализовать сценарий на случай отказа
При выходе за границы массива причиной отказа является вызывающая сторона, и кроме изменения кода вызывающей стороны с этим ничего не поделаешь. Так же как к примеру и при попытке установки отрицательного GrowStep.
В отличии к примеру от эскепшинов при недостаточном количестве памяти при реалоке. Эти никуда не выпиливаются.

Добавлено через 4 минуты
Цитата Сообщение от Renji Посмотреть сообщение
У вас там все еще эпоха "640 килобайт хватит всем"?
Нет у нас эпоха гигантских моделей.

Добавлено через 3 минуты
Цитата Сообщение от Renji Посмотреть сообщение
Поэтому, оптимизировать можно только среднее время работы.
Приводился пример - массив со страничной организацией. Оптимизирует и использование памяти и скорость ставки в конец. Но при этом ценой оверхеда при доступе.
Опять же. Зависит от назначения. Если массив живет дольше одного таймфрейма то оптимизировать нужно время затрачиваемое в одном таймфрейме и равномерность распределения затраченного времени между таймфреймами.

Добавлено через 2 минуты
Цитата Сообщение от Renji Посмотреть сообщение
Еще одна планочка памяти на 16 гигабайт в Виларибо
После чего жителям Виларибо прийдетсяя скинутся на более дорогой процессор с большим количеством кеша чем жителям Вилобаджо

Добавлено через 10 минут
Цитата Сообщение от avgoor Посмотреть сообщение
вы просто навелосипедили свою, не побоюсь этого слова, убогую реализацию assert
Во первых в отличии от assert это очень помагает при отладке. Во вторых подсмотрено у Борланда. Это в строке убрали выпиливание да и то под вопросом. А в списках TList как было так и осталось.

Добавлено через 1 минуту
Цитата Сообщение от Renji Посмотреть сообщение
Ну или пилить вектор заточенный под строго определенные размеры.
А еще лучше набор векторов под разные сценарии использования.

Добавлено через 10 минут
Цитата Сообщение от hoggy Посмотреть сообщение
любая моральная иде покажет стек вызовов
Покажет. Только этот стек нужно видеть в момент возникновения ошибки. При этом иметь возможность не только видеть стек но и перейти в место вызова и посмотреть локальные данные вызывающих в момент возникновения ошибки. Именно экскепшн и позволяет останавливаться в момент возникновения ошибки без раскидывания брекпоинтов по всему коду. Это при наличии кода вызываемой стороны. А при отсутствии брекпоинты и кидать не куда (извращения в духе дизассемблировать и найти куда бряк тыкнуть не рассматриваем). Но все равно остается возможность остановится именно на сбойном вызове.
Если заметили даже штатные либы от всех производителей идут в двух видах бинарника - debug и release. Чем они по вашему отличаются кроме выпеленной в release части проверок?

Добавлено через 5 минут
Цитата Сообщение от Renji Посмотреть сообщение
У вас там все еще эпоха "640 килобайт хватит всем"?
Ну ну. Каждый лишний байт в структуре данных запросто может вылиться в лишние 100MB в структуре модели. и это далеко не предел.
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
08.04.2016, 04:18 38
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Основа отказоустойчивости в корректности работы программ. trow это еще и инструмент который способен сообщить о некорректности программы на этапе отладки.
Кстати, вы в курсе про модификатор nothrow?
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Нет у нас эпоха гигантских моделей.
Если у вас там что-то гигантское, переполняющее 16-гигабайтовые планки памяти, то используется B-дерево и ему подобные структуры. И там все равно двукратный оверхед по памяти.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Приводился пример - массив со страничной организацией. Оптимизирует и использование памяти и скорость ставки в конец. Но при этом ценой оверхеда при доступе.
Если вы про "дораспределять страницы размером кратным степени двойки", то оно достигается ценой не константного времени доступа по индексу. Ибо номер страницы будет равен номеру старшего бита индекса, а нахождение старшего бита - логарифмическая сложность. "Массивом" такое является в той же степени, что и std::map<int,int>.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
После чего жителям Виларибо прийдетсяя скинутся на более дорогой процессор с большим количеством кеша чем жителям Вилобаджо
Не придется. Если элементы массива в конце узла никто не читает, на загрузку кеша они никак не влияют, даже если их там миллион. Исключая, конечно, вырожденный случай "узлы идут в памяти строго друг за другом и читаются строго по порядку".
0
2082 / 1573 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
08.04.2016, 04:46  [ТС] 39
Цитата Сообщение от Renji Посмотреть сообщение
Ибо номер страницы будет равен номеру старшего бита индекса, а нахождение старшего бита - логарифмическая сложность
При размере страницы 2^k номер страницы будет Id>>k. А номер элемента в странице (Id&(1<<k-1)). Для произвольного же размера страницы номер страницы будет Id/PageSize а номер элемента Id%PageSize. При этом подразумевается что для отдельно взятого массива размер страницы постоянен весь его жизненный цикл.
Как будто никогда банки видеопамяти не переключали ей богу. Может все роблемы что эпоху "На всех 640k" не застали?
Цитата Сообщение от Renji Посмотреть сообщение
Если у вас там что-то гигантское
У меня просто деревья объектов. К примеру как на форме ввода вывода. В принципе по организации ничем от этого не отличается к примеру компановка модели ЛА из объектов-подузлов, так же как и компоновка модели города из отдельных зданий состоящих из составных частей, так же и иерархия 3D сцены и т.д. и т.п. И все эти штуки должны хранить и изменять свои состояния и взаимосвязи и в соответствии с ними так или иначе взаимодействовать. И если зданий от 100K, итемов вообще немерянно, управляемых пользователем объектов тоже десятки тысяч... при этом состояние каждого объекта тоже может быть набором объектов содержащих взаимосвязи.
Цитата Сообщение от Renji Посмотреть сообщение
Если элементы массива в конце узла никто не читает
Если они статически прописаны в последнем узле (этот ваш массивчик для ускорения 16 элементов) то и в кеш они пойдут вместе с самим узлом.
Цитата Сообщение от Renji Посмотреть сообщение
конечно, вырожденный случай "узлы идут в памяти строго друг за другом и читаются строго по порядку"
Ну почему же вырожденный? Если подгрузка дерева была одним махом из файла то лежать узлы будут по порядку. Ну а страничек у кеша много, поэтому в кеше будут страницы содержащие наиболее часто используемые страницы памяти содержащие узлы. Меньше размер узла - больше узлов в кеше. Больше размер узла - для такого же количества узлов в кеше нужен больший кеш. При этом учитывая что огромная часть обработки крутится обычно по соседним в памяти узлам (нод и его прямые потомки, во всяком случае при создании дерева путем десериализации файла они обычно где то рядом) то и в кеш они будут попадать примерно теми группами которые обрабатываются.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
08.04.2016, 05:34 40
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
При размере страницы 2^k номер страницы будет Id>>k.
А я подумал что k растет вместе с массивом и он получается списком из страниц на 2, 4, 8, 16... 2^k элементов.
Если брать фиксированное 2^k, то все еще хуже. Размер страницы маленький - тормозит реалок списка страниц. Размер страницы большой - просто дикий оверхед по памяти, мой буфер на 16 элементов и рядом не лежал.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
И если зданий от 100K, итемов вообще немерянно, управляемых пользователем объектов тоже десятки тысяч...
Зданий от ста тысяч, в каждое здание злой Renji добавил буфер на 16 интов. А это, между-прочим, 64 байта. 100 000 зданий*64 байта, итого шесть с хвостиком мегабайт. Если для вас шесть мегабайт - серьезная трата, отнесите свой ПК в музей наконец.
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Ну почему же вырожденный? Если подгрузка дерева была одним махом из файла то лежать узлы будут по порядку. Ну а страничек у кеша много, поэтому в кеше будут страницы содержащие наиболее часто используемые страницы памяти содержащие узлы.
Потому что в кеше содержатся не четырехкилобайтовые страницы, а 32/64 байтовые кеш-ряды. И вероятность того что два наугад взятых узла дерева совершенно случайно оказались в одном кеш-ряде крайне мала. А если не оказались - полный ряд придется читать и тому узлу, и другому. А то и все два ряда, так как вы же выравниванием данных на границу 32/64 байт не озаботились, да?
0
08.04.2016, 05:34
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.04.2016, 05:34
Помогаю со студенческими работами здесь

error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall Vector<int>::Vector<int>(void)" (?0?$Vector@H@@QAE@XZ) в функции _main
//Vector.h #include &lt;iostream&gt; #include &lt;Windows.h&gt; #include &lt;climits&gt; #include &lt;vector&gt;...

О возможностях С++
Можно ли с помощью С++ авторизоваться на каком-то сайте ? Скачать определенный файл с сайта ?...

Как можно увеличить размер вектора, который является элементом вектора vector<vector<int>>arr(n, vector <int>)
Написал программу, которая создает вектор 'а' векторов 'b', вектора 'b' содержат 2 числа. Стало...

О возможностях ACCESS
Здравствуйте, товарищи специалисты, суть вопроса такова: Возможно-ли в акесе реализовать бд...

О возможностях Java
Доброго времени суток! Господа, прошу прощения за столь глупый вопрос. Но гуглить и читать совсем...

Вопрос о возможностях Delphi
Доброго времени суток, уважаемые программисты и сисадмины! Хотел узнать, возможно ли в Delphi...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru