2010-11-05 3 views
15

В различной коде C, я вижу константы, определенные как это:#defining константа в C++

#define T 100 

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

const int T = 100; 

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

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

+0

'T' не обязательно будет использовать память после компиляции программы. – GManNickG

ответ

28

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

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

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

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

+0

Собственно, последний бит не соответствует действительности. 'const int x = rand();' является законным, но впоследствии не может использоваться в качестве параметра массива или шаблона. – MSalters

+0

@MSalters: Whoops; виноват. Исправлено, чтобы добавить, что объект, содержащий const, должен быть инициализирован с постоянным выражением, чтобы он мог использоваться в самом постоянном выражении. Спасибо за исправление. –

2

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

3

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

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

7

Существует не требование, чтобы T хранился «в памяти» во втором случае, если вы не сделаете что-то вроде этого. Это справедливо для всех переменных.

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

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

1

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

1

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

x->sameNameAsPreprocessorToken 

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

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

0

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

Смежные вопросы