2011-03-07 22 views
9

Cuando tiene una variable global estática en un archivo de encabezado C++, cada unidad de traducción que incluye el archivo de encabezado termina con su propia copia de la variable.Variable global estática utilizada por la función miembro en línea

Sin embargo, si declaro una clase en el mismo archivo de cabecera, y crear una función miembro de esa clase, implementado en línea dentro de la declaración de la clase, que utiliza la variable global estática, por ejemplo:

#include <iostream> 

static int n = 10; 

class Foo { 
public: 
    void print() { std::cout << n << std::endl; } 
}; 

entonces veo un comportamiento un poco extraño bajo gcc 4.4:

  1. Si compilo sin optimización, todos los usos de la función de miembro de utilizar la copia de la variable de una de las unidades de traducción (la primera que se menciona en el comando g ++ línea).

  2. Si compilo con -O2, cada uso de la función miembro utiliza la copia de la variable de la unidad de traducción en la que está hecha la caja.

Obviamente, este es un diseño realmente malo, por lo que esta pregunta es solo por curiosidad. Pero mi pregunta, sin embargo, es ¿qué dice el estándar de C++ sobre este caso? ¿Se está comportando correctamente g ++ dando diferentes comportamientos con o sin optimización habilitada?

+1

Posible duplicado: [palabra clave estática en el archivo h y enlace interno] (http://stackoverflow.com/questions/4276794/static-keyword-in-h-file-and-internal-linkage). –

Respuesta

12

La norma dice (3.2/5):

No puede haber más de una definición de un tipo de clase (cláusula 9), ... siempre satisfacen las definiciones los siguientes requisitos .. . en cada definición de D, nombres correspondientes, miraron según 3.4, se referirse a una entidad definida dentro de la definición de D, o se referirá a la misma entidad

Aquí es donde su código pierde. Los usos de n en las diferentes definiciones de Foo no se refieren al mismo objeto. Juego terminado, comportamiento indefinido, entonces sí, gcc tiene derecho a hacer cosas diferentes en diferentes niveles de optimización.

3,2/5 sigue:

excepto que un nombre puede referirse a un objeto const con interno o no vinculación si el objeto tiene el mismo tipo integral o de enumeración en todas definiciones de D, y el objeto se inicializado con una expresión constante (5,19), y el valor (pero no la dirección de ) del objeto se utiliza, y el objeto tiene el mismo valor en todos los definiciones de D

Por lo tanto, en su código de ejemplo podría hacer n en un static const int y todo sería encantador. No es una coincidencia que esta cláusula describa las condiciones bajo las cuales no hace ninguna diferencia si las diferentes unidades de medida "se refieren" al mismo objeto u objetos diferentes; todo lo que utilizan es un valor constante en tiempo de compilación, y todos usan el mismo.

+1

+1: A veces la ODR se viola de manera muy sutil –

+0

Excelente respuesta. Gracias. – jchl

Cuestiones relacionadas