dev - c++17
¿Cuáles son las reglas con respecto a la inicialización de estáticas no locales? (2)
Supongamos que tengo una clase cuyo único propósito son los efectos secundarios causados durante la construcción de sus objetos (por ejemplo, registrar una clase en una fábrica):
class SideEffectCauser {
public:
SideEffectCauser() { /* code causing side-effects */ }
};
Supongamos también que me gustaría que un objeto creara dichos efectos secundarios una vez para cada una de varias unidades de traducción. Para cada unidad de traducción, me gustaría poder poner un objeto SideEffectCauser
en el ámbito del espacio de nombres en el archivo .cpp, por ejemplo,
SideEffectCauser dummyGlobal;
pero 3.6.2 / 3 del estándar C ++ 03 sugiere que este objeto no necesita construirse a menos que se use un objeto o función en el archivo .cpp, y artículos como this y discusiones en línea como this sugieren que tales los objetos a veces no se inicializan.
Por otro lado, ¿hay una manera de crear una instancia de los objetos de una cadena con su nombre de clase? tiene una solución que se dice que funciona, y observo que se basa en el uso de un objeto de un tipo como SideEffectCauser
como miembro de datos estáticos, no como un elemento global, por ejemplo,
class Holder {
static SideEffectHolder dummyInClass;
};
SideEffectHolder Holder::dummyInClass;
Tanto dummyGlobal
como dummyInClass
son estáticas no locales, pero un dummyInClass
más detallado de 3.6.2 / 3 del estándar C ++ 03 muestra que ese pasaje se aplica solo a los objetos en el ámbito del espacio de nombres. Realmente no puedo encontrar nada en el estándar C ++ 03 que diga cuando las estadísticas no locales en el alcance de la clase se inicializan dinámicamente, aunque 9.4.2 / 7 sugiere que se aplican las mismas reglas que para las estadísticas no locales en el espacio de nombres alcance.
Pregunta 1: En C ++ 03, ¿hay alguna razón para creer que es más probable que se inicialice dummyGlobal
que dummyGlobal
? ¿O ambos pueden quedar sin inicializar si no se utilizan funciones u objetos en la misma unidad de traducción?
Pregunta 2: ¿Cambia algo en C ++ 11? La redacción en 3.6.2 y 9.4.2 no es la misma que la versión C ++ 03, pero, por lo que puedo decir, no hay una diferencia de comportamiento especificada para los escenarios que describí anteriormente.
Pregunta 3: ¿Existe una forma confiable de usar objetos de una clase como SideEffectHolder
fuera del cuerpo de una función para obligar a que se SideEffectHolder
efectos secundarios?
Creo que la única solución confiable es diseñar esto para compiladores específicos y tiempo de ejecución. Ningún estándar cubre la inicialización de globales en una biblioteca compartida, lo que creo que es el caso más complejo, ya que depende mucho del cargador y, por lo tanto, depende del sistema operativo.
Q1: no Q2: no en ningún sentido práctico Q3: no de manera estándar
Estoy usando algo similar con g ++ / C ++ 11 en Linux y registro mis fábricas como se esperaba. No estoy seguro de por qué no se llaman las funciones. Si lo que describe debe implementarse, significará que cada función en esa unidad debe llamar a la función de inicialización. No estoy muy seguro de cómo se podría hacer eso. Mis fábricas también están dentro de los espacios de nombres, aunque se denominan espacios de nombres. Pero no veo por qué no se llamaría.
namespace snap {
namespace plugin_name {
class plugin_name_factory {
public:
plugin_name_factory() { plugin_register(this, name); }
...
} g_plugin_name_factory;
}
}
Tenga en cuenta que la palabra clave estática ya no debería usarse más en C ++. A menudo es más lento tener una definición estática que una global.