Pregunta

Estoy revisando el código de un colega, y veo que tiene varias constantes definidas en el ámbito global como:

const string& SomeConstant = "This is some constant text";

Personalmente, esto me huele mal porque la referencia se refiere a lo que supongo que es un "anónimo". objeto construido a partir de la matriz de caracteres dada.

Sintácticamente, es legal (al menos en VC ++ 7), y parece ejecutarse, pero realmente prefiero que elimine el & amp; así que no hay ambigüedad en cuanto a lo que está haciendo.

Entonces, ¿esto es REALMENTE seguro y legal y estoy obsesionado? ¿El objeto temporal que se está construyendo tiene una vida garantizada? Siempre asumí que los objetos anónimos utilizados de esta manera se destruían después del uso ...


Entonces mi pregunta también podría generalizarse a la vida útil de un objeto anónimo. ¿El estándar dicta la vida útil de un objeto anónimo? ¿Tendría la misma vida útil que cualquier otro objeto en ese mismo alcance? ¿O solo se le da la duración de la expresión?


Además, al hacerlo como local, obviamente tiene un alcance diferente:

class A
{
    string _str;

public:
    A(const string& str) :
        _str(str)
    {
        cout << "Constructing A(" << _str << ")" << endl;
    }

    ~A()
    {
        cout << "Destructing A(" << _str << ")" << endl;
    }
};

void TestFun()
{
    A("Outer");
    cout << "Hi" << endl;
}

Muestra:

Construyendo A (Exterior); Destruyendo A (Exterior); Hola

¿Fue útil?

Solución

Es completamente legal. No se destruirá hasta que finalice el programa.

EDITAR: , está garantizado:

  

" Todos los objetos que no tienen dinámica   duración de almacenamiento, no tiene hilo   duración de almacenamiento, y no son locales   tener una duración de almacenamiento estático. los   el almacenamiento de estos objetos durará   durante la duración del programa   (3.6.2, 3.6.3). & Quot;

- Borrador de trabajo 2008, estándar para Lenguaje de programación C ++ , § 3.7.1 p. 63

Como señaló Martin, esta no es la respuesta completa. El borrador estándar de otras notas (§ 12.2, p. 250-1):

  

" Se crean temporarios de tipo de clase   en varios contextos: vinculando un valor   a una referencia (8.5.3) [...] incluso cuando   la creación del objeto temporal   se evita (12.8), toda la semántica   las restricciones se respetarán como si   El objeto temporal había sido creado.   [...] Los objetos temporales son destruidos   como el último paso para evaluar el   expresión completa (1.9) que (léxicamente)   contiene el punto donde estaban   creado. [...] Hay dos contextos   en el que los temporales se destruyen en   un punto diferente que el final de la   Expresión completa. [...] El segundo   contexto es cuando se vincula una referencia   a un temporal. El temporal al que   la referencia está vinculada o la   temporal que es el objeto completo   de un subobjeto al cual la referencia   está obligado persiste durante toda la vida de   la referencia excepto como se especifica   a continuación. "

Probé en g ++ si eso te hace sentir mejor. ;)

Otros consejos

Sí, es válido y legal.

const string& SomeConstant = "This is some constant text";

// Is equivalent too:

const string& SomeConstant = std::string("This is some constant text");

Por lo tanto, está creando un objeto temporal.
Este objeto temporal está vinculado a un const & amp; y, por lo tanto, su vida útil se extiende a la vida útil de la variable a la que también está vinculada (es decir, más larga que la expresión en la que se creó).

Esto está garantizado por el estándar.

Nota:

Aunque es legal. Yo no lo usaría. La solución más fácil sería convertirlo en un const std :: string.

Uso:

En esta situación, debido a que la variable está en alcance global, es válida para toda la longitud del programa. Por lo tanto, se puede usar tan pronto como la ejecución ingrese a main () y no se debe acceder después de que la ejecución salga de main ().

Aunque técnicamente puede estar disponible antes de esto, su uso en constructores / destructores de objetos globales debe atenuarse con el conocido problema del orden de inicialización de la variable global.

Pensamientos adicionales:

Esto, por otro lado, no sufrirá el problema:

char const* SomeConstant = "This is some constant text";

Y se puede usar en cualquier punto. Solo un pensamiento.

Puede ser legal, pero aún feo. ¡Deja fuera la referencia!

const string SomeConstant = "This is some constant text";

Es tan legal como feo.

Es legal extender una variable temporal con una referencia const , esto es utilizado por Alexandrescu ScopeGaurd vea esta excelente explicación de Herb Sutter llamada Un candidato para el " Más importante const " .

Dicho esto, este caso específico es un abuso de esta característica de C ++ y la referencia debe eliminarse dejando una cadena constante .

Al declararlo como constante (lo que significa que no se puede cambiar) y luego convertirlo en una referencia, lo que implica que alguien podría cambiarlo, parece, por lo menos, una mala forma. Además, como estoy seguro de que comprende, las variables globales son MALAS y rara vez son necesarias.

Bien, la gente me corrige si estoy fuera de lo más profundo, pero aquí están mis conclusiones escuchando todas sus excelentes respuestas:

A) es sintáctica y lógicamente legal, el & amp; extiende la vida útil del tempo / anónimo desde más allá del nivel de expresión hasta la vida de la referencia. Verifiqué esto en VC ++ 7 con:

class A { 
    public: A() { cout << "constructing A" << endl; }
    public: ~A() { cout << "destructing A" << endl; }
};

void Foo()
{
    A();
    cout << "Foo" << endl;
}

void Bar()
{
    const A& someA = A();
    cout << "Bar" << endl;
}

int main()
{
    Foo();    // outputs constructing A, destructing A, Foo
    Bar();    // outputs constructing A, Bar, destructing A
    return 0;
}

B) Aunque es legal, puede generar cierta confusión en cuanto a la vida útil real y la referencia en estos casos no le brinda ningún beneficio de declararlo como no referencia, por lo que la referencia probablemente debería evitarse e incluso puede Ser espacio extra. Como no tiene ningún beneficio, es una ofuscación innecesaria.

Gracias por todas las respuestas, fue una discusión muy interesante. En resumen: sí, es sintácticamente legal, no, no es técnicamente peligroso ya que la vida útil se extiende, pero no agrega nada y puede agregar costos y confusión, así que ¿por qué molestarse?

¿Suena bien?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top