2010-12-06 3 views
5

Tengo el siguiente código que compila sin advertencias (-Wall -pedantic) con g ++C++ pasando un literal de cadena en lugar de un const std :: string &?

#include <iostream> 
#include <string> 

using namespace std; 

class Foo 
{ 
public: 
    Foo(const std::string& s) : str(s) 
    { } 

    void print() 
    { 
     cout << str << endl; 
    } 

private: 
    const std::string& str; 
}; 


class Bar 
{ 
public: 

    void stuff() 
    { 
     Foo o("werd"); 
     o.print(); 
    } 
}; 


int main(int argc, char **argv) 
{ 
    Bar b; 
    b.stuff(); 

    return 0; 
} 

Pero cuando corro, sólo el salto de línea se imprime. ¿Qué está pasando?

Si tuviera que hacer estas cosas en el interior:

string temp("snoop"); 
Foo f(temp); 
f.print(); 

entonces funciona bien!

Respuesta

18

La razón por la cual esto falla es porque esencialmente compila a continuación.

Foo o(std::string("wurd")); 

En este caso el valor Foo está tomando una referencia a un objeto temporal que se elimina después del constructor completa. Por lo tanto, se mantiene en un valor muerto. La segunda versión funciona porque contiene una referencia a un local que tiene una vida útil mayor que la instancia Foo.

Para arreglar esto, cambie el memebr de const std::string& a const std::string.

+0

aplausos, no sé por qué mi cerebro no entendía eso: s –

+0

No tiene sentido tomar un valor de const como parámetro. Solo usa 'std :: string'. –

+1

@MilesRout Eso no es del todo cierto. Tal vez sepas que no quieres modificar la cadena, y al declararlo, permites que el compilador verifique que no. – Erik

2

Lo que está sucediendo es que la referencia 'str' se está inicializando para que apunte a la arg temporal, 's'. Es más o menos lo mismo que usar un puntero: estás contando con la existencia continuada de tu constructor arg, 's'. Cuando se elimina el temporal (después de que devuelve el constructor ftn), su referencia ahora apunta a la basura.

Para corregir, cambie str para que sea un objeto de cadena real y no una referencia.

const std :: string str;

De esta manera se realizará una copia de su cadena arg, y dicha copia tendrá la misma duración que su objeto Foo.

Cuestiones relacionadas