Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

Различие define и const

#cpp


В чем различие между этими определениями переменной:

#define N 100


и

const int n = 100;


Что из этих двух является более предпочтительным и в чем достоинства каждого?
    


Ответы

Ответ 1



Это очень дискуссионный вопрос у всех. Но в целом, в с++ лучше использовать const везде, где это возможно. Плюсы: на них действуют области видимости. компилятор относится к ним как к обычными переменным, доступным только на чтение. у них есть тип. У define это все - недостатки. Они действуют от места определения и до ... конца. Хотя, где этот конец будет - ещё нужно хорошо подумать. Они могут переопределять друг дружку и иногда искать, где именно было в очередной раз переопределено - ещё то удовольствие. Компилятор часто выдает очень "загадочные ошибки". Классический пример с макросом min/max. Файл windows.h определяет их. И может быть очень весело. Детали - NOMINMAX. Ещё у define есть большой недостаток - это то, что некоторые думают, что там есть скобки. А их нет. #define add(a,b) a+b if (add(x,y) * add(x,y)) {} кажется, что будет посчитано (x+y) в квадрате. А на самом деле - .... на самом деле x+y + x*y. Но мы немного отвлеклись. Такого сделать обычным const уже нельзя. Но легко сделать inline функциями. И их результат будет предсказуемый. Поэтому: eсли нужно просто определить константу - используйте const (даже само слово намекает). eсли нужно определить макрос - используйте функции (если хочется интересней - используйте inline, но компиляторы сейчас достаточно умные). если нужно усложнить код и добавить синтаскического сахара - тогда самое время использовать define. UPD А ещё хорошо найти книгу Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ - Скотт Майерс и почитать второй совет (в любом случае - там всю книгу можно читать и читать).

Ответ 2



В чистом языке С++, если у вас есть выбор между этими двумя вариантами, то ясно, что предпочтительным является именно вариант с const. Однако вопрос задан несколько ограничивающе, ибо почему-то предложены к рассмотрению только эти два способа. В рамках современного языка С++ у вас есть третий способ constexpr int N = 100; который фактически является унифицированным вариантом, специально предназначенным для создания констант времени компиляции, как именованных, так и вычислимых. В данном случае, если не лезть в иррелевантные детали, разницы между const и constexpr не будет, однако существует мнение, что использование constexpr предпочтительнее именно в вашем варианте - когда вас интересует именно константа времени компиляции, но совершенно не интересует ее адресная идентичность, т.е. вы никогда не будете рассматривать адрес этой константы. Вариант с const в рамках этого мнения условно "отодвигается" на роли, которые этот квалификатор играет в языке С, т.е. создание "неизменяемых переменных" в памяти. Но, опять же, такое различие существует лишь на уровне соглашений, т.е. разницы между const int и constexpr int в тривиальных применениях вы не заметите. Однако и у #define тоже есть свои преимущества. Ограничение на использование только либо const, либо #define варианта возникнет тогда, когда вы будете создавать кросс-компилируемый С и С++ код (например, заголовочные файлы библиотек, предназначенных для использования в обоих языках). Тогда вам в большинстве случаев придется пользоваться именно #define, ибо в языке С квалификатор const не создает констант. В языке С для создания именованных констант времени компиляции у вас есть только enum и #define. В качестве еще одного преимущества варианта с #define можно назвать очевидную (но часто забываемую) возможность использовать #define-константы в условных выражениях препроцессора, т.е. в #if. Ни const, ни constexpr вам там не помогут. Шаблонное метапрограммирование и появление в языке С++ таких C++17 свойств, как "static if" (if constexpr) тоже частично переносит такие применения из области препроцессора в область самого языка и, соответственно, снижает ценность #define-констант в С++, но тем не менее эта деталь тоже заслуживает упоминания.

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

Отправить комментарий