Различие define и const

282
28 марта 2017, 13:56

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

#define N 100

и

const int n = 100;

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

Answer 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 верных советов улучшить структуру и код ваших программ - Скотт Майерс и почитать второй совет (в любом случае - там всю книгу можно читать и читать).

Answer 2

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

constexpr int N = 100;

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

В данном случае, если не лезть в иррелевантные детали, разницы между const и constexpr не будет, однако существует мнение, что использование constexpr предпочтительнее именно в вашем варианте - когда вас интересует именно константа времени компиляции, но совершенно не интересует ее адресная идентичность, т.е. вы никогда не будете рассматривать адрес этой константы. Вариант с const в рамках этого мнения условно "отодвигается" на роли, которые этот квалификатор играет в языке С, т.е. создание "неизменяемых переменных" в памяти.

Но, опять же, такое различие существует лишь на уровне соглашений, т.е. разницы между const int и constexpr int в тривиальных применениях вы не заметите.

Однако и у #define тоже есть свои преимущества.

Ограничение на использование только либо const, либо #define варианта возникнет тогда, когда вы будете создавать кросс-компилируемый С и С++ код (например, заголовочные файлы библиотек, предназначенных для использования в обоих языках). Тогда вам в большинстве случаев придется пользоваться именно #define, ибо в языке С квалификатор const не создает констант.

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

READ ALSO
Как вывести введенную матрицу с++

Как вывести введенную матрицу с++

У меня возникла проблема, как вывести все введенные елементы массива, а не только последнюю строку матрицы

306
Проверить массив при помощи библиотеки assert

Проверить массив при помощи библиотеки assert

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

349
Наименьшее количество чисел в ряду

Наименьшее количество чисел в ряду

Дан ряд чисел(числа принимают значения от 1 до 9) ,нужно вывести какая цифра встречает реже всего в этом ряду,если таких цифр несколько вывести...

271
c++: как открыть файл из директории share/app_name?

c++: как открыть файл из директории share/app_name?

Предположим есть программа, которой для работы нужен файл, расположенный в паке share/app_nameЕсли у нас INSTALL_PREFIX=/usr, то файл соответственно будет...

268