Что сделало бы макросы препроцессора C ++ приемлемым инструментом разработки? - PullRequest
2 голосов
/ 17 августа 2011

Видимо макросами препроцессора в C ++ являются

обоснованно опасается и избегает сообщества C ++.

Однако есть несколько случаев, когда макросы C ++ полезны .

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

- оставляет меня с вопросом, что именно делает макросы препроцессора «злыми», или, как говорится в заголовке вопроса, какая функция ( или удаление функции ) будет нужен из макросов препроцессора, чтобы сделать их полезными в качестве «хорошего» инструмента разработки (вместо того, чтобы заполнить его, который всем стыдно при его использовании). (В конце концов, языки Lisp, похоже, включают макросы.)

Обратите внимание : Это , а не о #include или #pragma или #ifdef. Это примерно #define MY_MACRO(...) ...

Примечание: я не намерен считать этот вопрос субъективным. Если вы думаете, что это так, не стесняйтесь голосовать, чтобы перенести его на программистов.

Ответы [ 7 ]

3 голосов
/ 17 августа 2011

Макросы повсеместно считаются злом, потому что препроцессор - это глупый инструмент для замены текста, который практически не знает C / C ++.

Четыре очень веские причины, по которым макросы являются злыми, можно найти в C ++ FAQ Lite .

Где возможно, шаблоны и встроенные функции - лучший выбор. Единственная причина, по которой я могу подумать, почему C ++ все еще нуждается в препроцессоре - это #include s и удаление комментариев.

Широко оспариваемое преимущество состоит в том, чтобы использовать его для уменьшения повторения кода; но, как вы можете видеть из библиотеки препроцессора boost, нужно приложить немало усилий, чтобы злоупотребить препроцессором из-за простой логики, такой как циклы, что приводит к уродливому синтаксису. На мой взгляд, лучше писать сценарии на реальном языке программирования высокого уровня для генерации кода, чем использовать препроцессор.

1 голос
/ 31 июля 2012

Большинство злоупотреблений препроцессором происходит из-за недопонимания, цитируя Пола Менсонида (автор библиотеки Boost.Preprocessor ):

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

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

#define ADD(x, y) ((x) + (y))

Это совершенно неправильно.Запускает это через препроцессор:

#define ADD(x, y) ((x) + (y))
ADD(1, 2) // outputs ((1) + (2))

Но ответом должно быть 3, так как добавление 1 к 2 равно 3. Тем не менее вместо этого пишется макрос для генерации выражения C ++.Мало того, это можно рассматривать как функцию C ++, но это не так.Вот где это ведет к злоупотреблениям.Он просто генерирует выражение C ++, и функция - гораздо лучший способ.

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

Бывают ситуации, когда для макросов может быть приемлемо генерировать код C ++, если это не так.Размытые линии.Так же, как если бы вы использовали Python в качестве препроцессора для генерации кода, препроцессор может делать то же самое, и имеет то преимущество, что ему не требуется дополнительный шаг сборки.

Кроме того, препроцессор можно использовать с DSL, например здесь и здесь , но эти DSL имеют предопределенную грамматику в препроцессоре, которую он использует для генерации C ++код.На самом деле это не размывает линии, поскольку использует другую грамматику.

1 голос
/ 17 августа 2011

Существует множество случаев, когда разработчик C использует макросы, а разработчик C ++ использует шаблоны.

Очевидно, что существуют случаи, когда они полезны, но в большинстве случаев это вредные привычки из мира C, применяемые кC ++ от людей, которые считают, что такой язык называется C / C ++

Поэтому проще сказать «это зло», чем рисковать тем, что разработчик злоупотребляет ими.

1 голос
/ 17 августа 2011

Самое важное в макросах - это то, что они не имеют области видимости и не заботятся о контексте.Они почти инструмент замены текста дампа.Поэтому, когда вы #define max (.... тогда везде, где у вас есть max, он заменяется; поэтому, если кто-то добавляет чрезмерно общие имена макросов в свои заголовки, он имеет тенденцию влиять на код, для которого он не предназначен.

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

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

Кроме того, они не обеспечивают безопасность типов или перегрузку.

Иногда макросывозможно, хороший инструмент для генерации стандартного кода, например, с помощью boost.pp вы можете создать макрос, который поможет вам создавать перечисления, такие как:

ENUM(xenum,(a,b,(c,7)));

, который может расширяться до

enum xenum { a, b, c=7 };

std::string to_string( xenum x ) { .... }

Такие вещи, как assert (), которые должны реагировать на NDEBUG, также часто проще реализовать в виде макросов

1 голос
/ 17 августа 2011

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

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

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

0 голосов
/ 30 июля 2012

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

0 голосов
/ 17 августа 2011
  1. Макросы не обеспечивают безопасность типов
  2. Проблемы, когда параметры выполняются дважды, например #define MAX (a, b) ((a)> (b)? (A): (b))и примените его для MAX (i ++, y -)
  3. Проблемы с отладкой, так как их имена не встречаются в таблице символов.
...