2011-09-21 3 views
2

Pourquoi ce code peut-il s'exécuter correctement dans Code :: block. La BID rapporte queRenvoi d'une référence à une variable locale

avertissement: "référence à la variable locale « tmp » retour",

mais ouput le résultat "Bonjour tout le monde" avec succès.

#include <iostream> 
#include<string> 
using namespace std; 

const string &getString(const string &s) 
{ 
    string tmp = s; 
    return tmp; 
} 

int main() 
{ 
    string a; 
    cout<<getString("hello world")<<endl; 
    return 0; 
} 
+1

double possible de [retour l'adresse de la variable locale ou temporaire] (http://stackoverflow.com/questions/2744264/returning-the-address-of-local-or-temporary-variable) – iammilind

Répondre

1

Vous provoquez un comportement indéfini. La norme ne dit pas ce qui se passe dans ce cas, cependant votre compilateur l'a détecté.

2

En quittant une fonction, toutes les variables locales sont détruites. En renvoyant une référence à tmp, vous renvoyez une référence à un objet qui cesse bientôt d'exister (c'est-à-dire, techniquement, l'adresse d'une région de mémoire dont le contenu n'est plus significatif). L'accès à une telle référence dangling appelle ce que l'on appelle un «comportement indéfini» - et malheureusement, «travailler comme d'habitude» est une sorte de «comportement indéfini». Ce qui pourrait arriver ici est que std::string garde un petit tampon statique pour les petites chaînes (par opposition aux grandes chaînes, pour lesquelles il récupère la mémoire du tas), et en quittant getString l'espace de pile occupé par cette chaîne n'est pas mis à zéro, il semble toujours travailler.

Si vous essayez une construction de débogage, ou invoquez une autre fonction entre les deux (ce qui remplacera effectivement l'espace de la pile), cela ne fonctionnera plus.

+0

Apt Ajouter ** Ne pas faire cela ** et Ne pas compter que le compilateur vous renverra la chaîne valide dans certains cas, pour lesquels vous pourriez trouver que cela fonctionne, il n'y a aucune garantie que cela fonctionnera la prochaine fois. –

1

tmp disparaît au moment de votre retour de getString. L'utilisation de la référence renvoyée est un comportement indéfini, donc tout peut arriver.

Pour corriger votre code, retournez la chaîne en valeur:

string getString(const string &s) 
{ 
... 
0

Etes-vous sûr? Il devrait segfault (il le fera avec gcc sur la plupart des plates-formes). Ce code contient une erreur, et si vous avez de la chance et que cela fonctionne, alors vous effleurez un insecte méchant sous le tapis.

Votre chaîne est retournée par référence, qui est, plutôt que de faire une nouvelle chaîne qui est valable dans le contexte que vous retournerez dans, est retourné un pointeur vers un rassis, Destructed, objet, ce qui est mauvais. const string getString... fera comme la déclaration pour le type de retour de la fonction.

0

L'objet temporaire est désalloué, mais son contenu est toujours présent sur la pile, jusqu'à ce que quelque chose le réécrit. Essayez d'appeler quelques fonctions entre appeler votre fonction et l'impression de l'objet retourné:

const string& garbage = getString("Hello World!"); 
callSomeFunctionThatUsesALotOfStackMemory(); 
cout<< garbage << endl; 
0

standard C++ indique que la liaison d'un objet temporaire à une référence const prolonge la durée de vie du temporaire à la durée de vie de la référence elle-même. Donc le code devrait fonctionner sur n'importe quel compilateur standard, mais la pratique elle-même n'est pas très agréable à mon avis. Si vous utilisez votre chaîne actuellement inutilisée dans votre exemple comme chaîne a = getString ("Hello World!"), Vous en ferez simplement une copie, et dans le cas d'une chaîne const, & a = getString ("Hello World! ") mon pari que vous ne devriez jamais avoir votre garbaged temporaire.

0

Comme vous pouvez le voir, l'exemple ci-dessous est légèrement modifié en appelant goodByeString(). Comme les autres réponses déjà soulignées, la variable dans getString appelée tmp est locale. la variable sort de la portée dès que la fonction retourne. puisque la pile est allouée, la mémoire est toujours valide quand la fonction revient, mais dès que la pile se développe à nouveau, cette partie de la mémoire où tmp réside est réécrite avec autre chose. Ensuite, la référence à un contient des déchets.

Toutefois, si vous décidez de sortir b car il n'est pas retourné par référence, le contenu est toujours valide.

#include <iostream> 
#include<string> 
using namespace std; 

const string &getString(const string &s) 
{ 
    string tmp = s; 
    return tmp; 
} 

string goodByeString(const string &s) 
{ 
    string tmp = "lala"; 
    tmp += s; 
    return tmp; 
} 

int main() 
{ 
    const string &a = getString("Hello World!\n"); 
    string b = goodByeString("ciao\n"); 
    cout << a << endl; 
    return 0; 
} 
Questions connexes