Насколько дороги аргументы указателя NULL?

При реализации меню во встроенной системе на C(++) (AVR-Gcc) я получил указатель на функцию void, который принимает аргументы и обычно их использует.

// void function prototype
void (*auxFunc)(char *);

В некоторых случаях (на самом деле довольно много) функция на самом деле не нуждается в аргументе, поэтому я бы сделал что-то вроде:

if (something)    doAuxFunc(NULL);

Я знаю, что могу просто перегрузить функцию другим типом, но на самом деле я стараюсь этого не делать, так как создаю экземпляры нескольких объектов и хочу, чтобы они были легкими.

Является ли вызов нескольких функций с указателями NULL (когда они предназначены для фактического указателя) хуже, чем реализация многих других прототипов функций?


person falro    schedule 13.08.2012    source источник
comment
Что говорит профайлер?   -  person zoul    schedule 13.08.2012
comment
Как вы думаете, почему перегрузки тяжелы?   -  person Kerrek SB    schedule 13.08.2012
comment
@KerrekSB В основном потому, что их будет содержать (относительно) много объектов, а пространство во встроенных системах ценно. В данном случае меню является скорее вспомогательной частью основного функционала проекта.   -  person falro    schedule 13.08.2012
comment
@falro: В основном потому, что будет (относительно) много объектов, содержащих их. Вы понимаете, что перегрузка создает ровно два экземпляра вместо одного, даже для миллиона объектов? Не каждый объект получает новую копию исполняемого кода.   -  person Damon    schedule 13.08.2012
comment
@Damon Да, да, ты прав. Не думал, что один через.   -  person falro    schedule 13.08.2012
comment
Перегрузка только увеличит использование памяти для кода и данных. Но потребление памяти зависит от функции и не увеличивается для каждого объекта. Указатели на эти перегруженные функции, очевидно, будут масштабироваться для каждого объекта, который содержит указатель. Но потребление памяти на объект для перегруженных или неперегруженных функций такое же, как компилятор определяет, что использовать во время компиляции, и это становится простым вызовом функции в объектном коде.   -  person syplex    schedule 13.08.2012


Ответы (4)


Проверка на NULL является очень небольшой накладной задачей даже на микроконтроллере - предполагается, что сравнение с 0 будет молниеносным. Если вы перегрузите несколько функций, вы пожертвуете читабельностью ради (очень незначительного) улучшения производительности. Просто позвольте оптимизатору GCC делать свое дело, он довольно хорош в этом :)

person Community    schedule 13.08.2012

Посмотрите на дизассемблирование, он должен генерировать нуль (ноль) для передачи в качестве первого аргумента, который либо сжигает регистр, либо местоположение стека, если он сжигает регистр, то это может стоить вам push и pop, если вызывающая функция жажду регистров. (просто использование вызова функции может стоить вам push и pops, если функция не хватает регистров для реализации соглашения о вызовах).

Так что, вероятно, есть затраты, но их может быть недостаточно, чтобы изменить то, как вы делаете что-то.

person old_timer    schedule 13.08.2012

Проверка на 0 действительно дешева, перегрузка еще дешевле, так как во время компиляции решается, какую функцию выбрать.

Но если вы считаете, что ваши интерфейсы становятся слишком сложными из-за перегрузки, а ваша функция маленькая, вы должны объявить ее inline и поместить в заголовок. Checkig для 0 может быть легко оптимизирован любым приличным современным компилятором.

person Jens Gustedt    schedule 13.08.2012
comment
Поскольку это решение для встроенной системы, встраивание приведет к использованию большего объема памяти для кода, что в данном случае также дорого обходится. - person syplex; 13.08.2012
comment
@syplex: это очень сильно зависит от размера вызова функции и очистки. Встраивание может сэкономить место. Это особенно важно, когда разумный оптимизатор может удалить ненужные инструкции. Типичным простым примером является метод Foo::getBar, предоставляющий доступ только для чтения к элементу Bar в Foo. Это может закончиться простым вычислением смещения указателя и даже может быть объединено с другими вычислениями смещения. - person MSalters; 14.08.2012
comment
gcc теперь имеет функцию частичного встраивания. По сути, он создаст ядро ​​​​функции в зависимости от всех параметров, а затем встроит часть, которая может распространяться постоянно. Это не имеет больших накладных расходов. - person Jens Gustedt; 14.08.2012

Я думаю, что «компромисс» смехотворно низок для каждого подхода, но сейчас самое время провести тесты для себя. Если вы это сделаете, пожалуйста, отпишитесь о некоторых результатах :)

person SLOBY    schedule 13.08.2012