2010-11-25 23 views
10

Sin embargo, otra pregunta static. He leído la siguiente:palabra clave estática en el archivo h y vinculación interna

Y todavía no comprender el siguiente comportamiento: tengo una h archivo:

// StaticTest.h 
#include <stdio.h> 

static int counter = 0; 

struct A { 
    A() { 
     counter++; 
     printf("In A's ctor(%d)\n", counter); 
    } 
    ~A() { 
     counter--; 
     printf("In A's dtor(%d)\n", counter); 
    } 
}; 

static A a; 

Y dos cpp archivos:

// StaticTest1.cpp 
#include "StaticTest.h" 

int main() { 
return 0; 
} 

Y:

// StaticTest2.cpp 
#include "StaticTest.h" 

La salida del programa es:

In A's ctor(1) 
In A's ctor(2) 
In A's dtor(1) 
In A's dtor(0) 

Ahora, el constructor A 's se llama dos veces, ya que el h el archivo se incluye dos veces, y desde la instancia A llamada a se declara static, tiene un enlace interno y el compilador está contento. Dado que el counter también se declara estático, también tiene un enlace interno, y esperaría que su valor no se comparta en los dos archivos cpp --- pero el resultado del programa implica que el valor es compartido, ya que cuenta hasta 2

alguna idea?

EDIT: Cualquier respuesta con respecto a lo que se considera un "buen hábito de programación" en el contexto de la declaración de variables estáticas en h vs cpp archivos también se da la bienvenida.

+0

I * * quiero decir algo acerca de los detalles de implementación y alrededor de tiempo de compilación-inicializado valores estáticos frente a los valores estáticos de tiempo de ejecución-inicializado, pero no me siento seguro de publicarlo como una respuesta. Intenta dejar 'counter' sin inicializar e inicializándolo en' main() '. –

+0

@ Benoit Thiery: este es el código fuente completo. –

+0

@ Ignacio Vazquez-Abrams: de la página de MSDN: "Cuando declaras una variable, la variable tiene una duración estática y el compilador la inicializa a 0 a menos que especifiques otro valor" –

Respuesta

9

Si StaticTest.h se comparte entre los archivos de origen de diferencia, obtendrá un comportamiento indefinido.

Si define una clase o funciones en línea en diferentes unidades de traducción, sus definiciones deben ser las mismas (misma secuencia de tokens) y, crucialmente, cualquier identificador debe referirse a la misma entidad (a menos que un objeto const con enlace interno) como en la definición en otra unidad de traducción.

Usted viola esto porque counter tiene un enlace interno, por lo que en diferentes unidades de traducción el identificador en las definiciones de función se refiere a un objeto diferente.

Referencia: C++ 3.2 03 [basic.def.odr]/5.

+1

+1 C++ es un lenguaje difícil :) –

+1

No estoy seguro de que entiendo completamente tu respuesta - 'counter' no es una definición de clase, es una declaración de variable, y de todos modos, no es una vinculación interna lo que significa que puedo tener dos entidades, cada una en su propia unidad de traducción? –

+3

@Itamar Katz: Sí, tiene más de una entidad llamada 'contador' (cada una con enlace interno), pero está violando la ODR en la definición de' A', 'A :: A' y' A :: ~ A'. Aunque sus definiciones constan de las mismas secuencias de token (buenas), porque 'counter' tiene un enlace interno, cuando usa ese identificador en la definición de' A' se refiere a un objeto diferente en cada unidad de traducción por separado. Esto significa que las definiciones de 'A' no son las mismas en todas las unidades de traducción que violan la ODR. –

Cuestiones relacionadas