online ejemplos descargar definicion caracteristicas c++

ejemplos - c++ online



const estático vs#define (9)

¿Es mejor usar static const #define ? ¿O tal vez depende del contexto?

¿Cuáles son las ventajas / desventajas de cada método?


No se recomienda la definición de constantes mediante el uso de la directiva de preprocesador #define se aplica no solo en C++ , sino también en C Estas constantes no tendrán el tipo. Incluso en C se propuso usar const para constantes.


Personalmente, odio al preprocesador, así que siempre iría con const.

La principal ventaja de un #define es que no requiere memoria para almacenar en su programa, ya que realmente está reemplazando algún texto con un valor literal. También tiene la ventaja de que no tiene ningún tipo, por lo que se puede usar para cualquier valor entero sin generar advertencias.

Las ventajas de "const" s son que pueden ser delimitadas, y se pueden usar en situaciones donde se necesita pasar un puntero a un objeto.

Sin embargo, no sé exactamente a qué te refieres con la parte "estática". Si declaras globalmente, lo pondría en un espacio de nombre anónimo en lugar de usar estática. Por ejemplo

namespace { unsigned const seconds_per_minute = 60; }; int main (int argc; char *argv[]) { ... }


Por favor, mira aquí: static const vs define

por lo general, una declaración const (tenga en cuenta que no necesita ser estático) es el camino a seguir


Pros y contras de todo, según el uso:

  • enums
    • solo es posible para valores enteros
    • los problemas de conflictos de alcance / identificador correctos, especialmente en las clases enum de C ++ 11 donde las enumeraciones para la enum class X son desambiguadas por el alcance X::
    • fuertemente tipado, pero a un tamaño int suficientemente grande, firmado o no, sobre el que no tiene control en C ++ 03 (aunque puede especificar un campo de bit en el que se deben empaquetar si el enum es miembro de struct / class / union), mientras que C ++ 11 se establece de manera predeterminada en int pero puede ser establecido explícitamente por el programador
    • no puede tomar la dirección; no hay una, ya que los valores de enumeración se sustituyen de manera efectiva en línea en los puntos de uso
    • restricciones de uso más fuertes (por ejemplo, incremento - template <typename T> void f(T t) { cout << ++t; } no se compilará, aunque puede envolver una enumeración en una clase con constructor implícito, operador de casting y user- operadores definidos)
    • cada tipo de constante tomado de la enumeración envolvente, por lo que la template <typename T> void f(T) obtiene una instanciación distinta cuando pasa el mismo valor numérico de diferentes enumeraciones, todas las cuales son distintas de cualquier instancia real f(int) . El código objeto de cada función podría ser idéntico (ignorando los desplazamientos de dirección), pero no esperaría que un compilador / enlazador elimine las copias innecesarias, aunque podría verificar su compilador / vinculador si lo desea.
    • incluso con typeof / decltype, no se puede esperar que los numeric_limits brinden información útil sobre el conjunto de valores y combinaciones significativas (de hecho, las combinaciones "legales" ni siquiera se anotan en el código fuente, considere enum { A = 1, B = 2 } - es A|B "legal" desde una perspectiva de lógica de programa?)
    • el nombre de tipo de la enumeración puede aparecer en varios lugares en RTTI, mensajes del compilador, etc., posiblemente útil, posiblemente ofuscación
    • no puede usar una enumeración sin que la unidad de traducción realmente vea el valor, lo que significa que las enumeraciones de las API de la biblioteca necesitan los valores expuestos en el encabezado y make y otras herramientas de recompilación basadas en la marca de tiempo desencadenarán la recompilación del cliente cuando se modifiquen (mala !
  • conste
    • problemas de enfrentamiento / identificador correctamente manejados muy bien
    • fuerte, único, tipo especificado por el usuario
      • puede intentar "escribir" un #define ala #define S std::string("abc") , pero la constante evita la construcción repetida de temporales distintos en cada punto de uso
    • Una regla de definición complicaciones
    • puede tomar dirección, crear referencias de referencias a ellos, etc.
    • más similar a un valor no const , que minimiza el trabajo y el impacto si se cambia entre los dos
    • el valor se puede colocar dentro del archivo de implementación, lo que permite una recompilación localizada y solo enlaces de clientes para recoger el cambio
  • define
    • ámbito "global" / más propenso a usos conflictivos, que pueden producir problemas de compilación difíciles de resolver y resultados inesperados en tiempo de ejecución en lugar de mensajes de error; mitigar esto requiere:
      • identificadores largos, oscuros y / o centralmente coordinados, y el acceso a ellos no puede beneficiarse de la coincidencia implícita de espacio de nombres utilizado / actual / buscado Koenig, alias de espacio de nombres, etc.
      • mientras que la mejor práctica de triunfo permite que los identificadores de parámetros de plantilla sean letras mayúsculas de un solo carácter (posiblemente seguidas por un número), otros usos de identificadores sin letras minúsculas se reservan convencionalmente para las definiciones de preprocesador (fuera de la biblioteca OS y C / C ++) encabezados). Esto es importante para que el uso del preprocesador a escala empresarial siga siendo manejable. Se espera que las bibliotecas de terceros cumplan. Al observar esto, la migración de consts o enumeraciones existentes desde / hacia define implica un cambio en las mayúsculas y, por lo tanto, requiere modificaciones en el código fuente del cliente en lugar de una recompilación "simple". (Personalmente, escribo en mayúscula la primera letra de las enumeraciones, pero no las constelaciones, así que me gustaría llegar a la migración entre esos dos también, tal vez sea hora de reconsiderar eso).
    • más operaciones de tiempo de compilación posibles: concatenación literal de cadena, stringification (tomando el tamaño del mismo), concatenación en identificadores
      • La desventaja es que dado #define X "x" y algún uso de cliente a "pre" X "post" , si quiere o necesita hacer de X una variable variable en tiempo de ejecución en lugar de una constante, forza las ediciones al código del cliente (en lugar de solo recompilación), mientras que esa transición es más fácil desde un const char* o const std::string dado que ya obligan al usuario a incorporar operaciones de concatenación (por ejemplo, "pre" + X + "post" para la string )
    • no se puede usar sizeof directamente en un literal numérico definido
    • sin tipo (GCC no advierte si se compara con unsigned )
    • algunas cadenas de compilador / vinculador / depurador pueden no presentar el identificador, por lo que se verá reducido a mirar "números mágicos" (cadenas, lo que sea ...)
    • no puede tomar la dirección
    • el valor sustituido no tiene que ser legal (o discreto) en el contexto donde se crea #define, ya que se evalúa en cada punto de uso, por lo que puede hacer referencia a objetos aún no declarados, depender de la "implementación" que no necesita #define MICROSECONDS *1E-6 , crear "constantes" como { 1, 2 } que se pueden utilizar para inicializar matrices, o #define MICROSECONDS *1E-6 etc. (¡ definitivamente no se recomienda esto!)
    • algunas cosas especiales como __FILE__ y __LINE__ se pueden incorporar en la sustitución de macro
    • puede probar la existencia y el valor en sentencias #if para código que incluye condicionalmente (más poderoso que un "si" posterior al preprocesamiento, ya que el código no necesita ser compilable si no es seleccionado por el preprocesador), use #undef -ine, redefina, etc.
    • El texto sustituido debe ser expuesto:
      • en la unidad de traducción que utiliza, lo que significa que las macros en las bibliotecas para uso del cliente deben estar en el encabezado, por lo que make y otras herramientas de recompilación basadas en la marca de tiempo desencadenarán la recompilación del cliente cuando se modifiquen (¡mal!)
      • o en la línea de comandos, donde se necesita aún más cuidado para asegurar que el código del cliente sea recompilado (por ejemplo, el Makefile o el script que proporciona la definición debe aparecer como una dependencia)

Como regla general, utilizo las tecnologías y las considero la opción más profesional para el uso general (aunque las otras tienen una simplicidad que atrae a este viejo programador perezoso).


Si está definiendo una constante para compartir entre todas las instancias de la clase, use const estático. Si la constante es específica para cada instancia, simplemente use const (pero tenga en cuenta que todos los constructores de la clase deben inicializar esta variable miembro miembro en la lista de inicialización).


Si se trata de una pregunta en C ++ y menciona #define como alternativa, se trata de constantes "globales" (es decir, alcance del archivo), no de miembros de la clase. Cuando se trata de tales constantes en C ++ static const es redundante. En C ++, const tiene un enlace interno por defecto y no tiene sentido declararlos static . Entonces realmente se trata de const vs. #define .

Y, finalmente, en C ++ const es preferible. Al menos porque tales constantes son mecanografiadas y delimitadas. Simplemente no hay razones para preferir #define sobre const , aparte de algunas excepciones.

Las constantes de cadena, por cierto, son un ejemplo de tal excepción. Con #define d constantes de cadena, se puede usar la función de concatenación en tiempo de compilación de los compiladores C / C ++, como en

#define OUT_NAME "output" #define LOG_EXT ".log" #define TEXT_EXT ".txt" const char *const log_file_name = OUT_NAME LOG_EXT; const char *const text_file_name = OUT_NAME TEXT_EXT;

PD De nuevo, por si acaso, cuando alguien menciona static const como una alternativa a #define , generalmente significa que están hablando de C, no de C ++. Me pregunto si esta pregunta está etiquetada correctamente ...


Siempre prefiera usar las características del idioma sobre algunas herramientas adicionales como el preprocesador.

ES.31: No use macros para constantes o "funciones"

Las macros son una fuente importante de errores. Las macros no obedecen el alcance habitual y las reglas de tipo. Las macros no obedecen las reglas habituales para aprobar argumentos. Las macros garantizan que el lector humano vea algo diferente de lo que ve el compilador. Las macros complican la construcción de herramientas.

De C ++ Core Guidelines


Usar una constante estática es como usar cualquier otra variable constante en tu código. Esto significa que puede rastrear desde donde proviene la información, a diferencia de un #define que simplemente se reemplazará en el código en el proceso de precompilación.

Es posible que desee echar un vistazo a la FAQ C ++ Lite para esta pregunta: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7


  • Un const estático se tipea (tiene un tipo) y puede ser verificado por el compilador para su validez, redefinición, etc.
  • un #define puede redifundirse indefinidamente.

Por lo general, debe preferir las consts estáticas. No tiene ninguna desventaja. El procesador debe usarse principalmente para la compilación condicional (y, a veces, para trucos realmente sucios).