2012-07-04 33 views
7

El título básicamente lo dice todo, me pregunto cuándo se inicializarán los miembros estáticos de una clase C++ y cuándo saldrán del alcance.Alcance variable de miembro estático de C++

Necesito esto para el siguiente problema. Tengo muchos objetos de una clase Foo y cada objeto necesita acceso a un recurso, encapsulado por otra clase de barra. La sincronización no es un problema, por lo que quiero que todos los objetos compartan la misma instancia de Bar.

Estoy usando un puntero administrado simple para el recuento de referencias.

¿Puedo hacer lo siguiente:

class Foo { 
private: 
    static managed_pointer<Bar> staticBar; 
public: 
    Foo() { 
     if(!staticBar) 
      staticBar = new Bar; 
    } 
    /* 
    * use staticBar in various non-static member functions 
    */ 
}; 

managed_pointer<Bar> Foo::staticBar = NULL; 

la managed_pointer staticBar debe eliminar el objeto barra tan pronto como se sale del ámbito - pero cuando sucede esto? cuando la última instancia de Foo es destruida? en la salida de la aplicación?

Gracias por su consejo!

+0

Vaya, gracias por corregir el error tipográfico. – Pontomedon

+0

La última instancia de Foo se destruye cuando simplemente elimina la última instancia o cuando existe su programa. Un miembro estático de una clase existirá sin importar cuántas instancias de la clase haya. – Gabi

Respuesta

13

static s y globales se inicializan justo antes de que comience el programa (antes de main se llama, el programa comienza realmente antes de eso) y salir de alcance después main salidas.

Excepciones: estática local (variables estáticas declaradas dentro de funciones) y miembros de clase de plantilla no utilizados static.

No tiene nada que ver con el número de instancias.

+0

Las variables locales estáticas no se inicializan antes de que comience el programa. – Gabi

+0

bien gracias. ¿A qué te refieres con "No tiene nada que ver con el número de instancias"? Instancias de la clase Foo? – Pontomedon

+1

sí, no importa cuántas instancias de Foo haya, todas compartirán Bar. –

2

La norma no especifica un orden preciso de inicialización, es específico de la implementación. Se crearán instancias al inicio del programa y se desasignarán al final.

Debe tener mucho cuidado con lo que está haciendo, porque si tiene otros objetos estáticos que dependen de este objeto para existir, es UB. No se sabe en qué orden serán inicializados.

Puede buscar algo como boost :: call_once para asegurarse de que se inicializa una vez, pero no confiaría en el orden en que se han inicializado las estadísticas.

Por lo que sé, tu código funcionaría, pero he sido mordido por el problema de inicialización estática antes, así que quería advertirte.

EDITAR: También en su código, cuando managed_ptr saldrá del alcance (final del programa), eliminará la memoria asignada automáticamente. Pero no debes hacer nada que no sea trivial en el destructor de Bar, ya que puedes activar UB llamando a otras instancias gratuitas o incluso a código que se ha eliminado (como me sucedió una vez cuando se eliminó una biblioteca dinámica). Esencialmente estás en un campo minado, así que ten cuidado.

+0

No tendré ningún otro 'static's en Foo, pero gracias por la advertencia, otro detalle bueno para tener en cuenta. EDIT: gracias también por la segunda advertencia, voy a tener cuidado. – Pontomedon

+0

Quise decir, otros objetos estáticos en su * programa *. Si más adelante decides tener otro objeto, digamos ReBar, que también es estático, y piensas "hey, puedo llamar a Bar :: Something porque está estático", debes tener cuidado. –

+1

Ah, está bien, creo que entiendo tu punto. – Pontomedon

1

La primera cosa que se sale de su pregunta es la idea errónea de que alcance y vida son conceptos equivalentes. Ellos no son. En algunos casos, como con las variables locales, de por vida está vinculado a un contexto particular, pero ese no es siempre el caso.

Una variable miembro estático clase ha alcance clase (es accesible cualquier lugar en el programa) y duración estática, lo que significa que se inicializará en orden con respecto a las otras variables estáticas en el mismo unidad de traducción, y en un orden indefinido con respecto a otras variables estáticas en otras unidades de traducción, antes de principal (advertencia: no es necesario realizar la inicialización antes de la primera instrucción en main, pero se garantiza que estará antes del primer odr- use de la variable).

+2

Una variable de miembro estática de clase tiene _class_ scope: solo es visible en contextos donde se buscan nombres dentro de la clase. Tiene una vida útil estática y un enlace externo (un tercer concepto que las personas a veces confunden con los dos que mencionas). Aún así, ha mencionado el punto esencial: la duración y el alcance son conceptos ortogonales. (Por lo menos hasta cierto punto. Hay _casos_ donde el alcance determina la vida útil.) –

+0

@JamesKanze: correcto, mi error. Gracias por mencionarlo. –

Cuestiones relacionadas