2010-11-05 17 views
15

en varios código C, veo constantes definidas como esto:constantes #defining en C++

#define T 100 

Mientras que en los ejemplos C++, es casi siempre:

const int T = 100; 

es mi entendimiento de que, en En el primer caso, el preprocesador reemplazará cada instancia de T por 100. En el segundo ejemplo, T se almacena en la memoria.

¿Se considera una mala práctica de programación #definir constantes en C++?

+0

'T' no necesariamente va a utilizar ninguna memoria después de compilar el programa. – GManNickG

Respuesta

28

¿Se considera una mala práctica de programación #definir constantes en C++?

Sí, porque todas las macros (que son las que definen #define s) están en un solo espacio de nombres y tienen efecto en todas partes. Las variables, incluidas const -variables calificadas, se pueden encapsular en clases y espacios de nombres.

Las macros se usan en C porque en C, una variable calificada const no es en realidad una constante, es solo una variable que no se puede modificar. Una variable calificada const no puede aparecer en una expresión constante, por lo que no se puede usar como un tamaño de matriz, por ejemplo.

En C++, un objeto Calificado const que se inicializa con una expresión constante (como const int x = 5 * 2;) es una constante y se puede utilizar en una expresión constante, por lo que puede y debe utilizar ellos.

+0

En realidad, el último bit no es verdadero. 'const int x = rand();' es legal, pero no puede usarse posteriormente como un parámetro de matriz o de matriz. – MSalters

+0

@MSalters: Whoops; mi error. Se corrigió para agregar que un objeto const debe ser inicializado con una expresión constante para que pueda ser utilizado en una expresión constante. Gracias por la corrección. –

2

Sí. Por lo menos, usa enums. Ambos const int y enum s se evaluarán en tiempo de compilación, por lo que tiene el mismo rendimiento. Sin embargo, es mucho más limpio, será más fácil de depurar (el depurador realmente sabrá qué es T), es seguro para el tipo y es menos probable que se rompa en expresiones complejas.

3

Debido a las diferencias entre los conceptos de constante en C y C++, en C básicamente estamos obligados a utilizar #define (o enum) la mayor parte del tiempo. const simplemente no funciona en C en la mayoría de los casos.

Pero en C++ no hay tal problema, por lo que es una mala práctica confiar en #define d constantes en C++ (a menos que realmente necesite una constante textualmente sustituida por alguna razón).

7

No es necesario que T se almacene "en memoria" en el segundo caso, a menos que haga algo como tomar la dirección del mismo. Esto es cierto para todas las variables.

La razón por la que el segundo es mejor es que el primero frecuentemente "desaparecerá" en la fase del preprocesador para que la fase del compilador nunca lo vea (y por lo tanto no se lo proporcione en la información de depuración). Pero ese comportamiento no es obligatorio por el estándar, sino que es una práctica común.

Hay poca necesidad de utilizar #define declaraciones más que para la compilación condicional. Las constantes individuales se pueden hacer con const, se pueden hacer múltiples constantes relacionadas con enum y las macros se pueden reemplazar con las funciones inline.

1

Las macros del preprocesador no respetan el alcance - es una simple sustitución de texto - mientras que static const int blah = 1; se puede incluir en un espacio de nombre. El compilador optimizará ambos casos (a menos que tome la dirección de esa variable) pero es seguro para el tipo y el alcance.

1

Sí. La razón más importante es que las definiciones del preprocesador no obedecen las reglas de alcance de la lengua, contaminando el espacio de nombres global, y peor - que están reemplazados incluso en casos como

x->sameNameAsPreprocessorToken 

Dado que las definiciones del preprocesador se sustituyen en el nivel textual , no se aplican otras propiedades normales de las variables: puede tomar la dirección de una const int, pero no de una constante # defined'd.

Según lo observado por otros, también suele perder la seguridad del tipo y la capacidad de depuración.

0

Otro punto interesante es que las constantes integrales globales podrían ser optimizadas por el compilador para que no ocupen ningún espacio (es decir, memoria). Por lo tanto, se pueden tratar como constantes literales cuando se usan y son tan óptimas como las constantes basadas en #define, sin todos los problemas del preprocesador.