variable programacion modificador metodo estatica c++ c

programacion - ¿Qué significa ''const static'' en C y C++?



variable static java (11)

const static int foo = 42;

Vi esto en algún código aquí en StackOverflow y no pude entender qué hace. Luego vi algunas respuestas confusas en otros foros. Mi mejor suposición es que se usa en C para ocultar el foo constante de otros módulos. ¿Es esto correcto? Si es así, ¿por qué alguien lo usaría en un contexto de C ++ donde puede hacerlo de forma private ?


A todas las excelentes respuestas, quiero agregar un pequeño detalle:

Si escribe complementos (por ejemplo, DLL o bibliotecas .so para ser cargadas por un sistema CAD), entonces static es un salvavidas que evita colisiones de nombres como este:

  1. El sistema CAD carga un complemento A, que tiene un "const int foo = 42;" en eso.
  2. El sistema carga un complemento B, que tiene "const int foo = 23;" en eso.
  3. Como resultado, el complemento B usará el valor 42 para foo, porque el cargador de complementos se dará cuenta de que ya existe un "foo" con un enlace externo.

Peor aún: el paso 3 puede comportarse de manera diferente según la optimización del compilador, el mecanismo de carga del complemento, etc.

Tuve este problema una vez con dos funciones auxiliares (mismo nombre, comportamiento diferente) en dos complementos. Declararlos estáticos resolvió el problema.


De acuerdo con la especificación C99 / GNU99:

  • static

    • es especificador de clase de almacenamiento

    • objetos de alcance de nivel de archivo de forma predeterminada tiene un enlace externo

    • objetos de ámbito de nivel de archivo con especificador estático tiene enlace interno
  • const

    • es tipo-calificador (es una parte del tipo)

    • palabra clave aplicada a la instancia inmediata a la izquierda, es decir,

      • MyObj const * myVar; - puntero no calificado para const tipo de objeto calificado

      • MyObj * const myVar; - const calificó el puntero al tipo de objeto no calificado

    • Uso más a la izquierda: aplicado al tipo de objeto, no variable

      • const MyObj * myVar; - puntero no calificado para const tipo de objeto calificado

ASÍ:

static NSString * const myVar; - Puntero constante a cadena inmutable con enlace interno.

La ausencia de la palabra clave static hará que el nombre de la variable sea global y podría generar conflictos de nombres dentro de la aplicación.


En C ++,

static const int foo = 42;

es la forma preferida de definir y usar constantes. Es decir, usar esto en lugar de

#define foo 42

porque no subvierte el sistema de seguridad tipo.


Es una pequeña optimización de espacio.

Cuando tu dices

const int foo = 42;

No está definiendo una constante, sino creando una variable de solo lectura. El compilador es lo suficientemente inteligente como para usar 42 cada vez que ve foo, pero también asignará espacio en el área de datos inicializada para él. Esto se hace porque, como se define, foo tiene un enlace externo. Otra unidad de compilación puede decir:

extern const int foo;

Para obtener acceso a su valor. No es una buena práctica ya que esa unidad de compilación no tiene idea de cuál es el valor de foo. Simplemente sabe que es una constante int y tiene que volver a cargar el valor de la memoria cada vez que se usa.

Ahora, al declarar que es estático:

static const int foo = 42;

El compilador puede hacer su optimización habitual, pero también puede decir "hey, nadie fuera de esta unidad de compilación puede ver foo y sé que siempre es 42, así que no hay necesidad de asignarle ningún espacio".

También debería tener en cuenta que en C ++, la forma preferida de evitar que los nombres escapen de la unidad de compilación actual es usar un espacio de nombres anónimo:

namespace { const int foo = 42; // same as static definition above }


Esa línea de código puede aparecer en varios contextos diferentes y aunque se comporta aproximadamente de la misma manera, existen pequeñas diferencias.

Espacio de nombre Alcance

// foo.h static const int i = 0;

'' i '' estará visible en cada unidad de traducción que incluya el encabezado. Sin embargo, a menos que realmente use la dirección del objeto (por ejemplo, '' &i ''), estoy bastante seguro de que el compilador tratará '' i '' simplemente como un tipo seguro 0 . Donde dos unidades de traducción más toman el '' &i '', la dirección será diferente para cada unidad de traducción.

// foo.cc static const int i = 0;

'' i '' tiene un enlace interno, por lo que no se puede hacer referencia desde fuera de esta unidad de traducción. Sin embargo, nuevamente, a menos que use su dirección, lo más probable es que se trate como 0 seguro.

Una cosa que vale la pena señalar es que la siguiente declaración:

const int i1 = 0;

es exactamente lo mismo que static const int i = 0 . Una variable en un espacio de nombres declarado con const y no declarada explícitamente con extern es implícitamente estática. Si piensa en esto, la intención del comité de C ++ era permitir que las variables const sean declaradas en los archivos de encabezado sin necesitar siempre la palabra clave static para evitar romper el ODR.

Alcance de la clase

class A { public: static const int i = 0; };

En el ejemplo anterior, el estándar explícitamente especifica que '' i '' no necesita ser definido si su dirección no es requerida. En otras palabras, si solo usa '' i '' como tipo 0 seguro, entonces el compilador no lo definirá. Una diferencia entre las versiones de clase y espacio de nombres es que la dirección de '' i '' (si se usa en dos o más unidades de traducción) será la misma para el miembro de la clase. Donde se usa la dirección, debe tener una definición para ello:

// a.h class A { public: static const int i = 0; }; // a.cc #include "a.h" const int A::i; // Definition so that we can take the address


Esta es la constante global visible / accesible solo en el módulo de compilación (archivo .cpp). Por cierto, el uso de estática para este propósito está en desuso. Es mejor usar un espacio de nombres anónimo y una enumeración:

namespace { enum { foo = 42 }; }


Falta un ''int''. Debería ser:

const static int foo = 42;

En C y C ++, declara una constante entera con el alcance del archivo local de valor 42.

¿Por qué 42? Si todavía no lo sabe (y es difícil de creer que no), es una referencia a la Respuesta a la vida, el Universo y Todo .


Hacerlo privado significaría que aparece en el encabezado. Tiendo a usar la forma "más débil" que funciona. Vea este clásico artículo de Scott Meyers: http://www.ddj.com/cpp/184401197 (se trata de funciones, pero también se puede aplicar aquí).


Mucha gente dio la respuesta básica, pero nadie señaló que en C ++ const defecto en static en el nivel del namespace de namespace (y algunos dieron información incorrecta). Consulte la sección estándar C ++ 98 3.5.3.

Primero algunos antecedentes:

Unidad de traducción: un archivo fuente después del preprocesador (recursivamente) incluía todos sus archivos de inclusión.

Enlace estático: un símbolo solo está disponible dentro de su unidad de traducción.

Enlace externo: un símbolo está disponible desde otras unidades de traducción.

En el nivel de namespace

Esto incluye el espacio de nombres global aka variables globales .

static const int sci = 0; // sci is explicitly static const int ci = 1; // ci is implicitly static extern const int eci = 2; // eci is explicitly extern extern int ei = 3; // ei is explicitly extern int i = 4; // i is implicitly extern static int si = 5; // si is explicitly static

En el nivel de función

static significa que el valor se mantiene entre llamadas a funciones.
La semántica de las variables static de la función es similar a las variables globales porque residen en el segmento de datos del programa (y no en la pila o el montón); consulte esta pregunta para obtener más detalles sobre static duración de las variables static .

A nivel de class

static significa que el valor se comparte entre todas las instancias de la clase y const significa que no cambia.


Sí, oculta una variable en un módulo de otros módulos. En C ++, lo uso cuando no quiero / necesito cambiar un archivo .h que desencadenará una reconstrucción innecesaria de otros archivos. Además, puse la estática primero:

static const int foo = 42;

Además, dependiendo de su uso, el compilador ni siquiera asignará almacenamiento para él y simplemente "en línea" el valor donde se usa. Sin la estática, el compilador no puede asumir que no está siendo utilizado en otro lugar y no puede en línea.


Tiene usos tanto en C como en C ++.

Como habrás adivinado, la parte static limita su alcance a esa unidad de compilación . También proporciona la inicialización estática. const solo le dice al compilador que no permita que nadie lo modifique. Esta variable se coloca en el segmento de datos o bss dependiendo de la arquitectura, y puede estar en la memoria marcada como de solo lectura.

Todo eso es cómo C trata estas variables (o cómo trata C ++ las variables del espacio de nombres). En C ++, un miembro marcado como static es compartido por todas las instancias de una clase dada. Si es privado o no, no afecta el hecho de que una variable es compartida por varias instancias. Tener const allí le advertirá si algún código intentaría modificar eso.

Si fuera estrictamente privado, cada instancia de la clase obtendría su propia versión (sin perjuicio del optimizador).