Название: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 15:50 Приветствую)
У меня такой вопрос: Имеется два указателя на объекты двух разных типов (A и B). Хотелось бы сравнивать не сами указатели, а их значения приведённые к типу size_t. Вот пример: Код
Т.е. корректно ли это будет всегда и везде работать? И есть ли какие-нить грабли? ??? Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 19, 2011, 16:05 Т.е. корректно ли это будет всегда и везде работать? И есть ли какие-нить грабли? Не хочется делать обязывающих заявлений, но да, всегда. Практичнее/приятнее привести к (char *) вместо size_t??? Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 16:08 Т.е. корректно ли это будет всегда и везде работать? И есть ли какие-нить грабли? Не хочется делать обязывающих заявлений, но да, всегда. Практичнее/приятнее привести к (char *) вместо size_t??? А в чём приимущество приведения к (char*) по сравнению size_t? Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 19, 2011, 16:15 А в чём приимущество приведения к (char*) по сравнению size_t? Чисто субъективное, приведение к (char *) весьма популярно в чистом "С", т.е. "Вас сразу поймут" :)Название: Re: тип size_t и сравнение указателей Отправлено: SimpleSunny от Март 19, 2011, 16:26 Не должно везде и всюду корректно работать.
Так как никто не гарантирует, что указатель поместится в size_t. Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 19, 2011, 16:34 Не должно везде и всюду корректно работать. Мне кажется это следует из правил адресной арифметики "С" (sizeof возвращает размер типа size_t)Так как никто не гарантирует, что указатель поместится в size_t. Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 16:40 Я тут нашёл статейку о size_t и ptrdiff_t
http://www.realcoding.net/articles/chto-takoe-sizet-i-ptrdifft.html В которой говориться, что в принципе проблем быть не должно, поскольку его (size_t) для этого и придумали, но есть исключение: это указатели на методы классов. Название: Re: тип size_t и сравнение указателей Отправлено: blood_shadow от Март 19, 2011, 18:49 мне кажется будет еще не плохо привести указатели к типу void* и сравнить их на равенство,
к тому же к void* можно неявно привести и операция сравнение это практически единственная что можно делать с void* Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 19, 2011, 19:07 Я тут нашёл статейку о size_t и ptrdiff_t http://www.realcoding.net/articles/chto-takoe-sizet-i-ptrdifft.html В которой говориться, что в принципе проблем быть не должно, поскольку его (size_t) для этого и придумали, но есть исключение: это указатели на методы классов. У меня были проблемы с реинтерпрет кастами, но я приводил указатель на A к указателю на B и пытался в нём что-то менять. Компилятору это не понравилось, он сгенерил неверный код. Поэтому в gcc такие преобразования делаю через юнион. В случае с size_t должно работать, но более правильно как blood_shadow сказал про void*: Код
или Код
Без реинтерпертов лучше обойтись, чтобы читающих код не пугать. Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 19, 2011, 19:15 Без реинтерпертов лучше обойтись, чтобы читающих код не пугать. Верное замечание, незачем выставлять мнимую "крутизну", лучшеКод Скромно и хорошо Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 19, 2011, 19:21 Код Скромно и хорошо сишный каст -- зло!! ..но для краткости сойдёт :) Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 19, 2011, 19:38 сишный каст -- зло!! ..но для краткости сойдёт :) Ой, мама дорогая, та где ж там такое зло? :) Хотели сравнить 2 адреса - ну и сделали. Или адрес уже "не (совсем) адрес" а нечто задроченое с помощью вумных xxx_cast ? :) Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 19, 2011, 19:42 сишный каст -- зло!! ..но для краткости сойдёт :) Ой, мама дорогая, та где ж там такое зло? :) Хотели сравнить 2 адреса - ну и сделали. Или адрес уже "не (совсем) адрес" а нечто задроченое с помощью вумных xxx_cast ? :) Вот скажет вам компилятор в один прекрасный день: "at line 123, error: сишный каст -- зло!!" и будет прав, а вам и сказать будет нечего. Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 19:55 Собственно, вопрос возник в контексте оптимизации libssc.
Там ранее при создании нового соединения или, например, при записи приоритета соединения и т.п. каждый раз проверяется весь список соединений и каждый раз при этом вызывается dynamic_cast (который по природе своей не быстр). Вот чтобы избавится от лишних его вызовов, я ввёл в базовый класс (base_connection) виртуальный метод: Код
И соответственно в унаследуемых классов этот метод определяю: Код Это всё позволяет не вызывать лишний раз dynamic_cast в функции compre: Код Собственно вот.. Спасибо) Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 19, 2011, 20:15 Вот чтобы избавится от лишних его вызовов, я ввёл в базовый класс (base_connection) виртуальный метод: Код
можно уменьшить и убыстрить так: 1. заменить size_t на void * 2. убрать у функции address атрибут virtual и =0 3. в теле address в базовом классе вернуть this (reinterpret_cast не нужен для преобразования в void*) 4. убрать address из наследников надо иметь ввиду, что вызов dynamic_cast по скорости близок к вызову виртуальной функции, поэтому заменяя dynamic_cast на виртуальную функцию много не выиграешь. но я бы сделал ещё радикальнее, перед вызовом compare (a, b) вставил бы: Код
-- так не будет расходоваться время на вызов виртуальной же функции compare, если адреса a и b сразу не равны. Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 19, 2011, 20:21 Вот скажет вам компилятор в один прекрасный день: "at line 123, error: сишный каст -- зло!!" и будет прав, а вам и сказать будет нечего. Мне было "сказать нечего" не один раз, на Mac учат "любить свободу" очень быстро. Жили себе спокойно на Classic. Раз - PowerPC, переписывайте, "просто так" Ваш код не пойдет. Ладно, только улеглось - бац! Carbon - портируйте. Ладно, несколько лет ОС не беспокоил, потом опять: портируйте на Univrsal Binary. Сейчас (тактично) намекают что от Carbon'а надо (срочно) избавляться. А давеча (10.7) Розетту кинули (пользователи на понтах, есть старый но нужный софт)Так что не верю я что можно написать "ну очень умный код" который уж наверняка будет совместим лет на 10 вперед. Если что случится - значит того не миновать, и нечего пытаться решать проблемы до их поступления Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 20:26 Цитировать можно уменьшить и убыстрить так: 1. Хорошо1. заменить size_t на void * 2. убрать у функции address атрибут virtual и =0 3. в теле address в базовом классе вернуть this (reinterpret_cast не нужен для преобразования в void*) 4. убрать address из наследников 2-4. так не получится по той причине, что мне не интересен адрес самого x_connection: я сравниваю адреса receiver, который является внутренней переменной соединения и содержит адрес объекта receiverА. Цитировать надо иметь ввиду, что вызов dynamic_cast по скорости близок к вызову виртуальной функции, поэтому заменяя dynamic_cast на виртуальную функцию много не выиграешь. Если так, то тогда получается, что нет смысла в этой оптимизации. :( ???Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 19, 2011, 20:41 1. Хорошо 2-4. так не получится по той причине, что мне не интересен адрес самого x_connection: я сравниваю адреса receiver, который является внутренней переменной соединения и содержит адрес объекта receiverА. да, в 2-4 я не прав. Если так, то тогда получается, что нет смысла в этой оптимизации. :( ??? Не знаю. Можно иметь в базовом классе void * addr; и его сравнивать. Но тогда в наследниках придётся колдовать с кастами, думаю эта возня не стоит результата. Стоит ли вообще оптимизировать операцию connect? Она ведь редко выполняется, гораздо реже вызова слота. Вообще в C++0x предлагали ввести мультиметоды для ускорения подобных операций (не знаю, прошёл ли пропозал). Но до светлого будущего редко случается дожить.. Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 20:56 Цитировать Не знаю. Можно иметь в базовом классе void * addr; и его сравнивать. Но тогда в наследниках придётся колдовать с кастами, думаю эта возня не стоит результата. Стоит ли вообще оптимизировать операцию connect? Она ведь редко выполняется, гораздо реже вызова слота. Вот я тож об этом сейчас подумал.. Оно того стоит? Если по времени вызов виртуальной функции и вызов оператора dynamic_cast одного порядка то нефиг и суетится..Цитировать Вообще в C++0x предлагали ввести мультиметоды для ускорения подобных операций (не знаю, прошёл ли пропозал). Но до светлого будущего редко случается дожить.. Ну почему же) В gcc 4.5.1 уже практически полностью поддерживает стандарт C++0x на сколько мне известно) Гоаорят, что уже лямбды можно использовать)Кстати, в libsig++ вообще не проверяется при создании нового соединения его наличие. Т.е. если подряд вызвать connect с одним и тем же слотом то слот будет повторно вызван :( Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 19, 2011, 21:05 Так что не верю я что можно написать "ну очень умный код" который уж наверняка будет совместим лет на 10 вперед. Если что случится - значит того не миновать, и нечего пытаться решать проблемы до их поступления Очень умный не получится, кто же спорит. Но дурные фичи лучше не использовать. Тем более, что касты не так часто нужны, и на 99% это static_cast и dynamic_cast. Сишный каст зло, потому что: 1. не имеет почти никаких ограничений (reinterpret_cast гораздо слабее), можно кастить тип, а заодно убить константность 2. трудно находится поиском 3. затуманивает смысл (не понятно, какой именно каст хотел сделать автор) Ну конечно в таком простом примере сишный каст не страшен, но написать static_cast 1 раз не очень сложно, мне кажется. В вашем примере тоже странно выглядит, кстати: (char *) a == (char *) b, читающий на секунду задумается, почему именно char*, может это сравнение строк каких-то? Может в этих классах строки вначале? Может у них operator char * есть? Надо использовать void * для таких вещей. Когда код формально верный, то читается легче, перестаёшь всё время подозревать, что автор -- идиот. Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 19, 2011, 21:10 Цитировать Так что не верю я что можно написать "ну очень умный код" который уж наверняка будет совместим лет на 10 вперед. Если что случится - значит того не миновать, и нечего пытаться решать проблемы до их поступления и Цитировать Сишный каст зло, потому что: 1. не имеет почти никаких ограничений (reinterpret_cast гораздо слабее), можно кастить тип, а заодно убить константность 2. трудно находится поиском 3. затуманивает смысл (не понятно, какой именно каст хотел сделать автор) Ну конечно в таком простом примере сишный каст не страшен, но написать static_cast 1 раз не очень сложно, мне кажется. В вашем примере тоже странно выглядит, кстати: (char *) a == (char *) b, читающий на секунду задумается, почему именно char*, может это сравнение строк каких-то? Может в этих классах строки вначале? Может у них operator char * есть? Надо использовать void * для таких вещей. Когда код формально верный, то читается легче, перестаёшь всё время подозревать, что автор -- идиот. == Мораль: Надо верить)) Хуже не будет) Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 20, 2011, 10:11 Сишный каст зло, потому что: 1) Интересно посмотреть пример показывающий выгоды reinterpret_cast <char *> по сравнению с незатейливым (char *)1. не имеет почти никаких ограничений (reinterpret_cast гораздо слабее), можно кастить тип, а заодно убить константность 2. трудно находится поиском 3. затуманивает смысл (не понятно, какой именно каст хотел сделать автор) Ну конечно в таком простом примере сишный каст не страшен, но написать static_cast 1 раз не очень сложно, мне кажется. В вашем примере тоже странно выглядит, кстати: (char *) a == (char *) b, читающий на секунду задумается, почему именно char*, может это сравнение строк каких-то? Может в этих классах строки вначале? Может у них operator char * есть? Надо использовать void * для таких вещей. Когда код формально верный, то читается легче, перестаёшь всё время подозревать, что автор -- идиот. 2) static_cast не приведет указатель к size_t 3) согласен, для "просто сравнения" (void *) приятнее, но (char *) позволит вычислить разницу между адресами что бывает нужно 4) Спорно/проблематично кто там больше "затуманивает". Часто текст превращается в демонстрацию знания C++ и автор озабочен не содержательной частью а лишь той самой "формальной грамотностью". Продравшись через все навороты обнаруживается, что дела-то "пшик", ф-циональность слаба. А бывает и наоборот Вот пример совершенно "не кошерного" кода (доставшегося мне в наследство) Код Автор весьма интенсивно пользует dynamic_cast в др. местах, но здесь решил сделать так - и у него были резоны. Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 20, 2011, 11:29 1) Интересно посмотреть пример показывающий выгоды reinterpret_cast <char *> по сравнению с незатейливым (char *) интересно посмотреть пример показывающий выгоды вытирания рта салфеткой по сравнению с простым рукавом рубашки.. 4) Спорно/проблематично кто там больше "затуманивает". Часто текст превращается в демонстрацию знания C++ и автор озабочен не содержательной частью а лишь той самой "формальной грамотностью". Продравшись через все навороты обнаруживается, что дела-то "пшик", ф-циональность слаба. А бывает и наоборот Я не к тому, что надо писать идеальный код, но туман на пустом месте не нужен. С формальностью тоже легко перебрать -- один раз видел в коде 50 строчек с шаблонами, нужных, чтобы убрать 1 ворнинг о сравнении unsigned >= 0. При прочих равных лучше кривой хак и строчка с комментом, чем формально правильное решение на страницу. Вот пример совершенно "не кошерного" кода (доставшегося мне в наследство) ... Автор весьма интенсивно пользует dynamic_cast в др. местах, но здесь решил сделать так - и у него были резоны. Младший бит указателя всё равно пропадает, стандартная оптимизация, но исполнение спорное (надо задачу видеть, чтобы оценить). Как раз классический пример, когда const легко потерять. Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 20, 2011, 12:48 1) Интересно посмотреть пример показывающий выгоды reinterpret_cast <char *> по сравнению с незатейливым (char *) интересно посмотреть пример показывающий выгоды вытирания рта салфеткой по сравнению с простым рукавом рубашки..Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 20, 2011, 13:25 А вот привести примерчик где reinterpret_cast сработает как надо а "просто приведение" нет bool chek_set_true (void const *opts, std::string const &opt_name) { cmd_line_options_map & cmd = *(cmd_line_options_map*) opts; return cmd [opt_name] == "true"; } тип параметра opts передать уже нет возможности (ошибка проектирования, но неисправимая, пишется плагин). Автор кастит сишным кастом и теряет const. Вообще-то автор знал, что std::map::operator[] это не константная операция, но проспал этот момент. Если бы был использован reinterpret_cast, то компилятор бы не дал потерять const, ссылка стала бы const, и компилятор ругнулся бы на cmd [opt_name]. А так в мап добавляются новые параметры, на что код в другом месте реагирует презабавным образом. Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 20, 2011, 13:56 У меня тут ещё вопрос возник:
Корректно ли тогда будет такая конструкция работать: Код ??? Или с указателями на функции такое уже не пройдёт? Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 20, 2011, 14:17 Проверил сейчас, что быстрее работает: вызов виртуальной функции или dynamic_cast:
Разницы практически никакой нет, едва заметный эффект начинает появлятся только после миллиона вызовов.. Так что смысла в этой оптимизации, реально 0. Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 20, 2011, 14:34 У меня тут ещё вопрос возник: Корректно ли тогда будет такая конструкция работать: Код ??? Или с указателями на функции такое уже не пройдёт? Не пройдёт. И с указателями на члены-данные не пройдёт. Проблема в том, что они могут быть размером в 2 указателя, для классов с виртуальными функциями. К тому же это не настоящие указатели. В общем не стоит их в воид запихивать, даже если сработает, то будет завязано на компилятор. Проверил сейчас, что быстрее работает: вызов виртуальной функции или dynamic_cast: Разницы практически никакой нет, едва заметный эффект начинает появлятся только после миллиона вызовов.. и кто побеждает-то? Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 20, 2011, 14:57 Цитировать и кто побеждает-то? Получается весьма забавный результат: побеждает dynamic_cast ???Вот сам тест: Код Суть эксперимента такова: Есть базовый класс Base с чисто виртуальными двумя функциями print() и type(). От него наследуются два класса DerivedInt и DerivedF в которых данные функции переопределяются. Но также в этих классах я ввожу не виртуальные методы myFunc(). Далее создаётся список, содержащий указатели на базовый класс Base: Код
И заполняется объектами на DerivedInt и DerivedF (случайным образом): Код Затем проверяется вызовы dynamic_cast виртуальных функций: Код Думаю, что тест не совсем чист, поскольку я не учитываю издержки связанные с оператором static_cast Название: Re: тип size_t и сравнение указателей Отправлено: brankovic от Март 20, 2011, 16:44 Получается весьма забавный результат: побеждает dynamic_cast ??? У меня тоже, интересный результат. Наверное из-за того, что функция type что-то делает (возвращает значение), а dynamic cast полностью инлайнится. Ещё, на static_cast нет никаких издержек, он влияет только на этапе проверки программы на ошибки. Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 20, 2011, 19:45 Код
А вообще все эти расходы пренебрежимо малы даже когда надо затачивать скорость. Др. дело типичная ошибка "лучших собаководов STL" - просмотр new/malloc в цикле вычислений (часто грубый, на push_back, insert) Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 20, 2011, 20:42 Код
Идея теста была сравнить что быстрей: dynamic_cast или вызов виртуальной функции. Conclusions: Хотя в данном случае dynamic_cast оказался быстрее, забивать голову и тратить время на подобные оптимизации - бредовая идея) Лучше потратить его (время) на обдумывание архитектуры и рассмотрения возможных вариантов её расширения в будущем) Код: 4) Спорно/проблематично кто там больше "затуманивает". Часто текст превращается в демонстрацию знания C++ и автор озабочен не содержательной частью а лишь той самой "формальной грамотностью". Продравшись через все навороты обнаруживается, что дела-то "пшик", ф-циональность слаба. А бывает и наоборот Название: Re: тип size_t и сравнение указателей Отправлено: Akon от Март 20, 2011, 21:25 2 m_ax: попробуй увеличить иерархию наследования и рассматривать динамик-каст самого последнего потомка к самой первой базе.
Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 20, 2011, 21:33 2 m_ax: попробуй увеличить иерархию наследования и рассматривать динамик-каст самого последнего потомка к самой первой базе. Не спорю, вполне вероятно, что при этом ситуация может изменится, но мне как то фиолетово) У меня реально используется обин базовый класс и два наследуемые от него. Раньше я считал, что в моём случае (пример приведённый выше лишь отражает общую картину) dynamic_cast - очень медленная штука по сравнению с вызовом виртуальной функции, однако, как оказалось для беспокойства нет причин и я оставил вариант с dynamic_cast. Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 20, 2011, 22:23 Формальная грамотность, формальная грамотность.. Грамотность при написании кода - это элементарное уважение к читающему код и залог безопасности (не маловажный факт). Понты, по мне - это когда в коде встречаются сплошь и рядом сомнительные хаки и прочие грабли, на которые разве что не наступит (и то сомнительно) сам автор, в то время, как истинная причина всего этого безобразия - плохая архитектура и чрезмерный С-консерватизм. :) Ну давайте немного поспорим. Можно покритиковать Ваш кусочек кода? :) Вот прямо "близлежащий"Код
- имя "l" просто безобразно, я уже подслеповат и вижу "1" - TYPE_F выглядит "ну очень в стиле С", (как впрочем и test_virtual_fun). Лучше смотрится Base::TYPE_F - "type" весьма сомнительное название для метода, а myFunc лишено всякой определенности - чего это подается ListBase & (а не const ListBase &) если содержимое контейнера указателей остается неизменным? Где же залог безопасности? :) Архитектура: Мне кажется я понял Вашу идею, но тест виртуалов выглядит странно. Зачем грузить тест static_cast и вызовом невиртуала myFunc? Что меряем если львиная доля посвящена другому? Логичнее так (в теле цикла) Код А для второго теста так Код Так что негусто ни с "уважением к читающему" ни с "архитектурой". Однако вынужден признать: с демагогией - все отлично :) Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 20, 2011, 22:41 Цитировать Ну давайте немного поспорим. Можно покритиковать Ваш кусочек кода? Улыбающийся Вот прямо "близлежащий" Ну я исчо учусь) Потом этот тест я написал на коленках за минут 10 чисто для себя, чтоб потом его нафиг удалить)) У меня ещё техника не доведена до такого автоматизма, чтоб так прям сразу, даже простой тест, писать идеологически правильно)) Логичнее критиковать то, откуда непосредственно ноги растут: libssc) Цитировать Так что негусто ни с "уважением к читающему" ни с "архитектурой". Однако вынужден признать: с демагогией - все отлично Улыбающийся Я исправлюсь :) Название: Re: тип size_t и сравнение указателей Отправлено: Igors от Март 21, 2011, 11:39 А задумка у Вас была хорошая: проверить на деле вместо того чтобы гадать (или утверждать с чужих слов) . Мой тест (исходник приаттачен) печатает такое
Цитировать TestVirtual time(sec): 0.28 sum = 157286400 Примечание "sum" нужна чтобы компилятор не схлопнул код в releaseTestNonVirtual time(sec): 3.192 sum = 157286400 dynamic_cast вызывается дважды, поэтому второе время нужно поделить на 2. Но все равно, dynamic_cast ощутимо (в неск раз) медленнее вызова virtual. Согласен с Akon, что dynamic_cast зависит от сложности построения базового класса. Немного глянув в отладчике: вроде для "не POD" типа static_cast поет примерно ту же песню что и dynamic_cast (это просто впечатление) При всем этом: dynamic_cast "достаточно быстр" и экономить на нем неразумно (3 секунды на 200 миллионах вызовов) Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 21, 2011, 12:52 И всё же я считаю, что Ваш тест не совсем чист:
Во-первых, как Вы уже заметили, dynamic_cast в функции TestNonVirtual вызывается дважды. Во-вторых, Код В функции TestVirtual Виртуальная функция вызывается один (T_v - время вызова виртуальной функции) раз + время на суммирование (T_sum). Всё хорошо. В функции TestNonVirtual Дважды вызывается dynamic_cast (T_dyn - время вызова) + время вызова не виртуальной функции (T_nv) и + операция суммирования (T_sum). Я хочу сказать, что нужно сравнивать чистый вызов dynamic_cast и чистый вызов виртуальной функции. Зачем вообще все эти операции суммирования? Оптимизатор можно просто отключить) Например в debug версии. Кстати, в debug версии мой тест показывает следующие результаты (при трёх запусках): Код И получается, что виртуальная функция быстрее dynamic_cast (в данном конкретном случае) в 1.04 раз. Название: Re: тип size_t и сравнение указателей Отправлено: m_ax от Март 21, 2011, 13:56 Да, хочу добавить вот что:
Запустил Ваш тест в release и в debug версии со следующим изменением кода: Код Посмотрим, для начала, какую ошибку мы допускаем пренебрегая временем вызова не виртуальной функции. Т.е. сейчас мы сравниваем вирт. и не вирт. функции при прочих равных условиях. Результат (release): Код А в debug: Код Сравнивая, можно сделать вывод, что оптимизатор не так просто обмануть, во всяком случае на трюк с суммированием он не ведётся)) Теперь запомним это отношение: время вирт.ф / время не вирт. ф. = 1.529/0.995 = 1.54 И запустим в debug Ваш изначальный вариант: Код Теперь, вспоминая, что время TestNonVirtual нужно поделить на два: t = 5.348/2 = 2.674 и далее его ещё нужно поделить на отношение, которое было найдено выше, т.е. на 1.54: В результате имеем: Код Отношение этих значений есть: 1.736/1.696 =1.02 Что находится в хорошем согласии с моими результатами в debug версии. |