2012-04-18 10 views
9

Estoy escribiendo un juego Cocos2D-X donde el jugador, los enemigos y otros personajes almacenan sus atributos en un CCMutableDictionary, que es algo así como una clase de decorador para std::map<std::string, CCObject*>. Se puede acceder a un valor en el diccionario a través del método CCMutableDictionary::objectForKey(const std::string& key).Forma correcta de hacer const std :: string en un archivo de cabecera?

Ahora, en un archivo de cabecera incluida por muchos de mis archivos .cpp, tengo unos const char * const cadenas para acceder a los valores en los diccionarios, así:

// in Constants.h 
const char* const kAttributeX = "x"; 
const char* const kAttributeY = "y"; 

// in a .cpp file 
CCObject* x = someDictionary->objectForKey(kAttributeX); 

Así, corrígeme si me estoy equivocado, pero el constructor de copias de std::string se está llamando y hay un std::string temporal en la pila cada vez que llamo a uno de los métodos objectForKey anteriores usando un const char* const, ¿verdad?

Si es así, creo que sería más eficiente en tiempo de ejecución si esas claves constantes de atributos ya fueran objetos std::string. ¿Pero cómo hago eso derecho manera?

Definición de ellos en el constants.h presentar como la siguiente compila bien, pero tengo la sensación de que algo no está bien:

// in Constants.h 
const std::string kAttributeX = "x"; 
const std::string kAttributeY = "y"; 

Mis disculpas si esta pregunta ya ha sido pedido. Parece que no pude encontrar la respuesta exacta que estaba buscando aquí en StackOverflow.

Respuesta

18

El código que escribió está perfectamente bien, al menos como solo #include el archivo Constants.h en un solo archivo fuente. Si usa el archivo de encabezado en múltiples archivos fuente, tendrá las mismas variables definidas varias veces. El uso correcto de las constantes en los archivos de cabecera son dividirlas en una cabecera (Constants.h) que contiene los declaraciones de las variables, y un archivo de origen (Constants.cpp), que contiene los definiciones de las variables:

la archivo de cabecera:

#ifndef CONSTANTS_H 
#define CONSTANTS_H 

extern const std::string kAttributeX; 
extern const std::string kAttributeY; 

#endif 

el archivo de origen:

const std::string kAttributeX = "x"; 
const std::string kAttributeY = "y"; 
+0

Entonces, si las cadenas están definidas en un archivo .cpp, ¿cuándo se crean instancias? –

+0

@NatWeiss Se crearán instancias junto con todas las demás variables globales. –

+0

¿El problema con las variables definidas varias veces se aplica cuando eran "const char * const"? Estoy bastante seguro de que no es así, pero no entiendo por qué. ¿Qué le da a "const char * const" el privilegio de ser definido en una sola ubicación que incluya su valor (mucho más agradable, IMO, especialmente en términos de mantenimiento)? – Brent212

2

Su segunda opción hace que cada uno de los VA riables que se crearán en cada unidad de traducción (archivo cpp que incluye el encabezado) lo que aumentará ligeramente el tamaño del código así como también agregará un poco del costo del tiempo de ejecución (construyendo todas esas cadenas durante el lanzamiento y destruyéndolas durante la terminación del proceso).

La solución suggested by Joachim funciona pero encuentro que declarar y definir variables por separado es un poco molesto. Personalmente odio repetirme a mí mismo, tampoco me gusta decir lo mismo una y otra vez ...

No conozco una buena solución para esto en C++ propiamente dicho, pero los compiladores con los que trabajé es compatible con algo como __declspec(selectany) para que pueda definir la variable en el archivo de encabezado y solo obtener un objeto instanciado (en lugar de uno para cada unidad de traducción).

__declspec(selectany) extern const std::string kAttributeX = "x"; 

(Por qué tanto externconst y ver this answer).

Aún tiene el inconveniente de pagar el precio de inicialización de todas las variables globales durante el inicio del proceso. Esto es aceptable el 101% del tiempo (dar o recibir el 2%) pero puede evitarlo usando objetos perezosos (tengo written about something similar here).

Cuestiones relacionadas