Дизайн библиотеки: процедурный против ООП

#c #oop

#c #ооп

Вопрос:

Я взвешиваю различия в производительности между следующими, и у меня могут быть некоторые недостатки в моем понимании компилятора. Насколько я понимаю:

 typedef struct{
    void (*foo)();
} Foo;
 

Выделял бы достаточно места для указателя каждый раз, когда он объявляется.

Это приводит меня к разработке таких функций, как:

 void foo(Foo*);
 

Является ли это ненужной оптимизацией?

Комментарии:

1. По некоторому определению, вся оптимизация не нужна, если нет узких мест. Но я бы лично посоветовал использовать 2-й стиль, если нет необходимости в 1-м. Даже если это не узкое место, я не вижу крошечной эмуляции фактического синтаксиса ООП, которую вы получаете в 1-м, чтобы стоило хранить что-то дополнительное, а не просто явно передавать this указатель, как во 2-м. Обратите внимание также, что если бы 1-му варианту требовался экземпляр, ему также нужно было бы передать его. Таким образом, он хранит ненужный указатель и все равно должен передавать Foo* его в любом случае. Но: это, вероятно, только мое мнение и / или зависит от более конкретного контекста, который не показан

2. Спасибо, я искал второй взгляд на это.

3. Широкое обсуждение парадигм и лучших практик может быть более уместным на softwareengineering.stackexchange.com

4. Обратите внимание, что OP спрашивал не о стиле, а о производительности, что по теме.

5. Ваша кодовая база уже претерпела изменение языка программирования, не возможно ли, что сейчас ей нужен рефакторинг до более современной версии C и, возможно, несколько других вариантов дизайна, прежде чем переходить к другому языковому сдвигу?

Ответ №1:

Проблема с указателями на функции для эмуляции синтаксиса, подобного C , заключается не столько в том, что вам нужно передавать объект «this» через параметр, а в том, что вы довольно резко блокируете шансы компилятора на встраивание этих вызовов функций-членов.

Дизайн OO заключается не в использовании определенного синтаксиса, а в разработке программы. Поэтому, если вы можете использовать foo_set(amp;foo) вместо foo.set(amp;foo) , первое, вероятно, приведет к гораздо более эффективному коду. Особенно при вызове простых функций «установщик / получатель» из самой единицы перевода «класс».

Также, пожалуйста, обратите внимание, что void (*foo)(); это устаревший стиль в C, и вы должны писать void (*foo)(void); вместо этого.

Комментарии:

1. Спасибо! Я полагал, что в этом случае частью проблемы была вставка — вот почему я специально ссылался на свои пробелы в знаниях в разработке компилятора. Будет ли компилятор игнорировать все указатели при встраивании или это зависит от того, сколько уровней косвенности?

2. @EvanHendler Указатели на объекты как часть списка параметров «исчезают» во время встраивания, как и любой другой параметр. Проблема здесь в том, что компиляторы обычно могут не выполнять встроенные вызовы функций через указатели на функции, что связано не с тем, какие параметры вы используете, а с характером указателей на функции во время выполнения.

3. Хорошо, это соответствовало тому, о чем я думал, без каламбура. Просто нужна фиктивная проверка.

4. В основном во время выполнения указателю присваивается адрес функции, а затем, когда вы вызываете указатель на функцию, он разыменовывает указатель и вызывает функцию.

5. Если бы он был встроен, это разрушило бы всю цель, потому что теперь указатель на функцию статичен.