2010-07-15 8 views
9

Une question de base que je ne suis pas sûr de la réponse. La fonction de suivi est-elle valide?C++ retour référence/pile mémoire

std::vector<int> & test_function() { 
    std::vector<int> x; 

    // do whatever 

    return x; 
} 

Si oui, pourquoi? Le programme ne devrait-il pas supprimer x de la pile après le retour de la fonction? Merci.

Répondre

11

Le comportement est indéfini. Vous ne devez pas renvoyer de références à des variables locales.

+1

Merde, bat moi moi! – Anthony

+1

Le code affiché ne contient pas (à lui seul) de comportement indéfini. L'UB arriverait dans un autre code qui appelle cette fonction. –

8

La fonction est bien formée (syntaxiquement correcte), mais dès que la fonction revient, la référence renvoyée est invalide et ne peut plus être utilisée.

Pour clarifier: le code en question ne pas invoquer tout comportement indéfini. Vous pouvez appeler en toute sécurité cette fonction aussi longtemps que vous n'utilisez pas la valeur de retour, par exemple, ceci est valable:

test_function(); // ok 

Cependant, si vous essayez d'utiliser la valeur de retour (c.-à-initialiser une autre référence avec ou copie le référent dans un autre objet), alors vous invoquera un comportement non défini, car la durée de vie du référent (l'objet x) aura terminé (x sera détruit lorsque la fonction retourne, car il est une variable automatique):

std::vector<int>& vec = test_function(); // undefined 
std::vector<int> vec = test_function(); // undefined 
+0

Sur une note sérieuse, si la structure référencée est juste un groupe de POD (pas de pointeurs) ou est une primitive, si le cadre de pile normal est tenu, et vous copiez la valeur (ne pas contenir une référence, donc votre seconde exemple ici), la valeur locale d'origine sera correcte immédiatement après le retour ('mov esp, ebp; pop ebp; 'la trame de la pile locale n'est pas perturbée). Destructeurs, cependant, sont invoqués et les données peuvent être manipulées/changées. C'est la mauvaise façon d'y parvenir, cependant, et de prédire ce qui va se passer, même si on devine avec précision dans un endroit n'est pas portable. –

+0

@jMerliN: Même pour un objet de type POD, les résultats sont formellement indéfinis. La durée de vie d'un POD prend fin à la fin de sa durée de stockage. pour une variable locale, c'est au point que la fonction retourne. L'utilisation d'un objet après la fin de sa durée de vie entraîne un comportement indéfini. Est-ce que cela "fonctionne" en pratique avec des objets de type POD? Peut-être, mais comme vous le dites, ce n'est pas un comportement qui devrait être utilisé. –

+0

Il ne devrait certainement pas être invoqué lorsque multithread devient standard car l'emplacement de la pile qui a été peut-être déjà été réutilisé par un autre thread (Notez que la norme ne définit pas comment la pile ou le tas sont implémentés). –

0

Vous ne pouvez pas renvoyer une référence à une variable locale pour la même raison que vous ne pouvez pas retourner un poi nter à une variable locale, car au retour de la fonction, ces variables locales sont libérées et donc la référence ou le pointeur devient invalide.

2

Oui c'est valide, mais si vous essayez d'utiliser la valeur retournée, vous aurez un comportement indéfini.