2009-01-20 13 views
40

He visto códigos con estos dos estilos, no estoy seguro si uno es mejor que otro (¿es solo cuestión de estilo)? ¿Tiene alguna recomendación de por qué elegiría uno sobre otro?¿Definir constantes de cadena de clase en C++?

//Example1 
class Test { 

    private: 
     static const char* const str; 

}; 

const char* const Test::str = "mystr"; 

//Example2 
class Test { 

    private: 
     static const std::string str; 

}; 

const std::string Test::str ="mystr"; 
+1

¿Cómo es eso perturbador? –

Respuesta

55

Por lo general, debería preferir std::string sobre los indicadores de caracteres simples. Aquí, sin embargo, el puntero char inicializado con el literal de cadena tiene un beneficio significativo.

Hay dos inicializaciones para datos estáticos. El uno se llama inicialización estática, y el otro se llama inicialización dinámica. Para aquellos objetos que se inicializan con expresiones constantes y que son POD (como punteros), C++ requiere que su inicialización ocurra desde el principio, antes de que ocurra la inicialización dinámica. La inicialización de std :: string se realizará de forma dinámica.

Si tiene un objeto de una clase que es un objeto estático en algún archivo, y que necesita acceder a la cadena durante su inicialización, puede confiar en que ya está configurado cuando usa la versión const char* const, mientras utilizando la versión std::string, que no se inicializa estáticamente, no se sabe si la cadena ya está inicializada, porque el orden de inicialización de los objetos a través de los límites de la unidad de traducción no está definido.

+7

+1 He pasado tiempo depurando algunos bloqueos muy desagradables que resultaron ser causados ​​por instancias estáticas de una clase de cadena que se rompió debido a problemas con el orden de inicialización. ¡Evita instancias estáticas de 'std :: string'! –

+1

Me sorprendió mucho esta respuesta. ¿Hay alguna manera de hacerlo funcionar con std :: string? – loop

+0

@test: yes: 'std :: string const & safe_string_const() {std :: string estático const var =" const "; devolver var; } ' –

4

Hmmm, a std :: string no es lo mismo que un const char *. Normalmente me equivoco al utilizar std :: string porque es una clase que tiene muchas capacidades adicionales que hacen que sea mucho más fácil de usar.

Si el rendimiento es primordial y está utilizando const char * para la eficiencia, vaya por ese camino.

2

El primer ejemplo requiere menos sobrecarga para administrar la cadena (es decir, solo un puntero a la sección de TEXTO). Además, el segundo método puede requerir una asignación de montón también para copiar el literal de cadena al búfer de clase std: string. Entonces, terminarías con dos copias de los datos.

1

La segunda versión tiene la ventaja de que viene con una longitud precalculada y los otros beneficios de una clase de cadena desarrollada. El primero tiene la ventaja de que la única inicialización es simplemente asignar un puntero a datos estáticos ya cargados en la imagen ejecutable, donde el segundo tiene que inicializar la cadena desde ese mismo puntero.

+0

La primera versión tiene strlen ... –

+0

Sí, pero es una operación O (n), por lo que dependiendo del uso, eso puede ser un problema. – Eclipse

+0

Pero supongo que es solo un debate sobre los beneficios de std :: string vs char * en general. – Eclipse

3

Tiendo a favorecer std :: string's over char * al hacer C++. Prefiero std :: cadena principalmente por sus capacidades integradas, así como la comodidad y la seguridad de no tener que lidiar con punteros.

Sin embargo, como han mencionado otros, la versión de const char * puede ser favorable si está demasiado preocupado por el rendimiento. Me parece recordar que alguien inteligente dijo una vez que la optimización prematura es la raíz de todo mal (o algo así). :)

2

En proyectos grandes que involucran varias plataformas con diferentes compiladores y bibliotecas, muchos equipos y mucha gente hemos tenido repetidamente problemas con std :: strings estáticos. En algunas plataformas, la implementación de std: string no es segura para subprocesos. En una plataforma, el código optimizado del compilador omitió inicializar una cadena std: local de la const estática global. Después de perseguir algunos de estos problemas, solo permitimos constetes estáticos globales para los tipos incorporados.

1

En primer lugar, si no usaría un char *.Si desea una cadena ASCIIZ, definir uno de ellos directamente:

const char Test::str[] = "mystr";

En su mayor parte, eso es lo que haría uso. ¿Por qué perder tiempo y memoria en la sobrecarga de la clase de cuerda?

Tenga en cuenta que "sizeof (Test :: str)" le dará exactamente la longitud de la matriz, que es la longitud de la cadena, incluida la terminación NUL (strlen (str) +1).

+0

Es extraño decir que std :: string desperdicia memoria cuando desperdicia sizeof (Test :: str) al copiar un char de const perfectamente bueno [] a otro const char []. – MSalters

+0

¿Quién está copiando algo? Es "const int x = 5;" copiando algo? Solo hay un char [] que posee intrínsecamente el valor "mystr"; –

Cuestiones relacionadas