#defining константы в С++

В разных C-кодах я вижу константы, определенные следующим образом:

#define T 100

В то время как в примерах на С++ это почти всегда:

const int T = 100;

Я понимаю, что в первом случае препроцессор заменит каждый экземпляр T на 100. Во втором примере T фактически хранится в памяти.

Является ли это плохой практикой программирования для #define констант в С++?

Ответы

Ответ 1

Является ли это плохой практикой программирования для #define констант в С++?

Да, потому что все макросы (которые определены #define) находятся в одном пространстве имен, и они действуют повсеместно. Переменные, включая const -qualified variables, могут быть инкапсулированы в классы и пространства имен.

Макросы используются в C, потому что в C, a const -qualified переменная на самом деле не является константой, это просто переменная, которая не может быть изменена. A const -qualified переменная не может появляться в постоянном выражении, поэтому ее нельзя использовать как размер массива, например.

В С++ объект const -qualified, который инициализируется константным выражением (например, const int x = 5 * 2;), является константой и может использоваться в постоянном выражении, поэтому вы можете и должны использовать их.

Ответ 2

Нет необходимости хранить T "в памяти" во втором случае, если вы не сделаете что-то вроде этого. Это справедливо для всех переменных.

Причина, по которой вторая лучше, заключается в том, что первая часто "исчезает" на фазе предварительного процессора, так что фаза компилятора никогда не видит ее (и, следовательно, не дает ее вам в отладочной информации). Но это поведение не санкционировано стандартом, а распространенной практикой.

Не нужно использовать операторы #define, кроме как для условной компиляции. Одинарные константы могут быть выполнены с помощью const, множественные связанные константы могут быть выполнены с помощью enum, а макросы могут быть заменены на inline.

Ответ 3

Из-за различий между понятиями константы в C и С++ в C мы в основном вынуждены использовать #define (или enum) большую часть времени. const просто не работает в C в большинстве случаев.

Но в С++ такой проблемы нет, поэтому по-настоящему плохой практикой полагаться на константы #define d в С++ (если по какой-то причине вам действительно не нужна текстовая замена константы).

Ответ 4

Да. По крайней мере, используйте перечисления. Оба параметра const int и enum будут оцениваться во время компиляции, поэтому вы будете иметь одинаковую производительность. Тем не менее, он намного чище, будет легче отлаживать (отладчик действительно знает, что такое T), он безопасен по типу и реже ломается в сложных выражениях.

Ответ 5

Макросы препроцессора не уважают область - это простая подстановка текста - в то время как static const int blah = 1; может быть заключена в пространство имен. Компилятор по-прежнему будет оптимизировать оба случая (если вы не берете адрес этой переменной), но он безопасен по типу и области.

Ответ 6

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

x->sameNameAsPreprocessorToken

Поскольку определения препроцессора заменяются на текстовом уровне, другие нормальные свойства переменных не применяются - вы можете взять адрес int const, но не константу # define.d.

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

Ответ 7

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