Pull to refresh

Comments 46

compiler is your friend — use it often
© Кто-то из магистров =)
Всегда воспринимал эту фразу, как напуствие писать код так, что бы как можно больше ошибок проявились на стадии компиляции.
Но в данном контексте он тоже очень подходит.
Ой как здорово то. Но на мой взгляд лучше просто задуматься над тем что пытаешься сделать и понять, что указатель на функцию это как ее сигнатура, но только со звездочкой.
Наверное я слоупук, но у меня был период развивития, когда каждый раз, когда приходилось использовать указатель на функицю я тупил/гуглил, прежде чем выходило написать правильно :)
По-моему указатели на функции — это рудимент языка. Если уж речь о C++, то коли нам нужна функция как объект, то уж лучше сразу сделать из неё функциональный объект, а не мучаться с представлением в виде указателя.
Указатель на функцию — по сути самый шустрый метод реализации многих вещей.
Первое что в голову приходит — коллбэки и таблицы функций.
Многих, но отнюдь не всех.

Темплейты и функторы помогают компилятору гораздо эффективней делать оптимизацию. Классический пример — qsort() в plain С vs std::sort() из С++
Немного поправляю, для функторов компилятор создает отдельную специализацию того же std::for_each, и поэтому может встроить его тело в данную ф-цию.
В случае реализации через указатели на ф-ции, встраивание невозможно.

Конечно я не считаю время затраченное на вызов, огромным профитом, но всеже :)
>> В случае реализации через указатели на ф-ции, встраивание невозможно.

невозможно в общем случае, но в частных случаях, когда значение указателя можно статически вычислить и понять, что он указывает на функцию находящуюся в одной единице трансляции, открытая подстановка становится возможной…
никогда над этим не задумывался, но вприцнипе согласен — иногда это возможно, надеюсь компиляторы это делают.
Согласен. Например, я через указатель на функции реализую программирование на машинных кодах. Т.е. забиваю массив char[] опкодами, затем привожу указатель на начало массива к указателю на функцию. Все известные мне компиляторы С++ это едят и получается некое подобие jit-compilation. Кто знаком с .NET и с тем, как реализуется компиляция байт-кода в нативный — те меня поймут.
Причем другого способа передать управление в сегмент данных не существует =)
Да, об этом я и вел речь, только я вспоминал ACS интерпретатор в Hexen'е первом. Я помню его оттуда позаимствовал, когда свой двухмерный аналог Hexen писал :D
Главное поместить код в нужную страницу и разрешить его выполнение.

Если попытаться выполнить массив из хипа — ругнется с access violation.
Просто выделение памяти для массива надо организовать с помощью VirtualAlloc и передать ей атрибут доступа READ/WRITE/EXECUTE
Постараюсь опубликовать свой топик с программированием сопроцессора на C++ и последующим использованием этой возможности в коде C#.
Я впринципе согласен с вами, но ситуации бывают разными.
Некоторые апи могут требовать указатели на ф-ции, некоторым проектам лет по 10, некоторые код-конвеншны могут не одобрять использования темплейтс, и тд.

Цель заметки состояла не в том, что бы пропогандировать использование указателей на ф-ции, а в том что бы подсказать как можно сэкономить время и нервы некоторым программистам.
Да, об устаревших API не подумал, точно.
А если «код-конвеншны не одобряют использования темплейтс», то тогда это не C++, а C. Странно писать на C++ и не пользоваться темплейтами или исключениями (кстати вроде Гугл у себя запрещает искюлчения). Хотя в мире много странных вещей :)
Странно, но если код к примеру не ексцепшн сейф, тогда на использование ексцепшнов логично наложить ограничения типа: не бросать из утилит и использовать их только в полностью новых и безопасных учатках кода.

Хотя в любом случае подобные ограничения меня тоже повергают в ступор, но они, к сожалению, бывают. У нас, к примеру, главный программист, который в штатах наложил вето на использование ассертов.

У assert'ов есть несколько проблем в дизайне: во-первых, они выполняют проверки только в Debug-режиме (молчаливо подразумевая, что в Release проверок делать не надо), во-вторых, стандартное поведение assert'ов — это вызов функции abort(), которая остановит приложение. Это редко где бывает допустимо.
Это всё фича ассертов :)

Основная их цель проверить ошибки которые могут быть допущенны программистом.
Естественно внешние данные ассертами не стоит проверять.
Например если моя функция подразумевает (precondition), что переданный в нее вектор должен быть отсортирован, то я пишу в начале нечто вроде assert( is_sorted( v ); Это своего рода и комментарий и не замедлит работу программы в релизе.
Хорошо, пусть так.

Но: в релизе на вход функции могут подать не отсортированный массив? Если да — функция, получается, вернёт мусор?
Да, но если это не входные данные, т.е. программист не выспался и забыл отсортировать массив, мы скорее всего поймаем этот ассерт еще на стадии отладки или тестирования.

Не проверять в каждой фукнции правильность переданных параметров.
Т.е. подразумевается, что проверки на свои же ошибки писать глупо, плюс не эффективно, плюс можно погрязнуть в ифах. Но что бы улучшить себе немного жизнь — есть ассерты.
>> Не проверять в каждой фукнции правильность переданных параметров.
хотел написать:
Не нужно же проверять в каждой фукнции правильность переданных параметров.
а оно может и верно, про ассерты. Я вот тоже, бывало, напишу ассерт, а потом думаю — «а вдруг в дебаге не сработает, а в релизе вылезет?» и пишу рядом проверку того, что в ассерте уже без ассерта. Напишу, а потом думаю — а нафига тогда я ассерт писал?
сорри, не к тому посту коммент, я на пост qehgt отвечал.
Для таких случаев можно использовать макрос типа «Проверить условие ассертом, а потом еще если не пройдет кинуть исключение с текстом ошибки». В релизе ассерт пропадает, а исключение остается.
Рудимент ли? Конечно можно с помощью них яйца прищемить, и будет больно, но иногда они очень полезны
Когда же наконец в C++ появятся указатели на функции-члены произвольного класса?
Скорее всего, такую фишку по-простому реализовать не получится, поскольку в указателе на функцию-член класса должна храниться информация о расположении vtable относительно указателя на instance класса. Если же предположить, что у нас появился указатель на функцию-член произвольного класса, то этой информации там быть не может, следовательно, компилятор и рантайм не будет знать, как вызывать функции по таким указателям.
Я лично здесь вижу только 1 путь реализации — с добавлением RTTI на этапе взятия адреса. При взятии адреса от функции-члена в указатель будет записываться this и некая служебная информация, необходимая для вызова функции-члена (смещение vtable, или адрес метода). При вызове эта информация будет извлекаться для определения реального адреса функции-члена.
Жаль, что quick fix в Eclipse для плюсов не развит. А то можно было бы лениво писать
char func = &test::foo;
Потом наводить мышкой на func и кликать в всплывающем окошке «сменить тип func» :-)
От блин. А можно прочитать доки (в Страуструпе отлично), и писать все правильно, не запуская компилер, и быть уверенным что происходит.
как я понимаю в c++0x проблема буде решаться просто через auto (http://www2.research.att.com/~bs/C++0xFAQ.html#auto)
Угумс, а сейчас уже есть BOOST_AUTO.
А что, просто скопировать заголовок функции и заменить имя на (*varname), дописав classname:: в случае функции-члена, нельзя?
Что не говорите, но ТАКОЕ описание указателей на функции в С/C++ мог придумать только странномыслящий субъект.
«Вы говорите об этом так, как будто это что-то плохое» (с)
Хотя если чесно, я не помню откуда я это узнал, вполне возможно, что не придумал, а подсмотрел у кого-то :)
char c = &test::foo;
Чего? О_О Вы точно это хотелось написать. По теме — известная конструкция, о которой пишут чуть ли не в каждой книге, но неудобная и плохочитаемая. В продакшн коде такое, обычно не пользуют.
я вас не понял. о какой конструкции идет речь?
вы вроде пропустили в последнем объявлении имя переменной с :)
не, в последнем объявлении имя уже дал func
Проблема такого подхода — это когда увидите объявление указателя (в сообщении об ошибке или коде) и не поймете на что он собственно указывает.

ГОРАЗДО лучше воспользоваться правилом «право-лево» и больше никогда не мучаться.
Хе… я написал сотни темплейтов, но каждый раз забываю куда там пихать угловые скобки при объявлении специализации функции… :-( Темплейтокретинизм…
я тоже долго не мог запомнить как объявлять указатель на функцию. :-)
Sign up to leave a comment.

Articles