Question

Je recommence avec c ++ et je réfléchissais à la portée des variables. Si j'ai une variable à l'intérieur d'une fonction et que je retourne ensuite cette variable, la variable ne sera pas "morte". quand il est retourné parce que la portée dans laquelle il était était terminée?

J'ai essayé cela avec une fonction renvoyant une chaîne et cela a fonctionné. Quelqu'un peut-il expliquer cela? Ou du moins, dirigez-moi vers un endroit qui peut me l'expliquer, s'il vous plaît.

Merci

Était-ce utile?

La solution

  

Lorsque la fonction se termine, le   les étapes suivantes se produisent:

     
      
  • La valeur de retour de la fonction est   copié dans l'espace réservé qui était   mettre sur la pile à cet effet.

  •   
  • Tout ce qui suit le cadre de la pile   le pointeur est sorti. Cela détruit   toutes les variables et tous les arguments locaux.

  •   
  • La valeur de retour est extraite du   pile et est assigné comme valeur   de la fonction. Si la valeur de la   la fonction n'est assignée à rien,   aucune cession n'a lieu, et le   la valeur est perdue.

  •   
  • L'adresse de l'instruction suivante   pour exécuter est sorti de la pile,   et la CPU reprend l'exécution à   cette instruction.

  •   

La pile et le tas

Autres conseils

Lorsque vous renvoyez une valeur, une copie est faite. La portée de la variable locale se termine, mais une copie est faite et renvoyée à la fonction appelante. Exemple:

int funcB() {
  int j = 12;
  return j;
}

void A() {
  int i;
  i = funcB();
}

La valeur de j (12) est copiée et renvoyée à i afin que je reçoive la valeur de 12.

Cela dépend vraiment du type de variable que vous renvoyez. Si vous retournez une primitive, elle est renvoyée par copie, et non par référence, de sorte que la valeur soit copiée en haut de la pile (ou plus souvent dans un registre) où la fonction appelante peut l'obtenir. Si vous allouez un objet ou de la mémoire sur le segment de mémoire et renvoyez un pointeur, il ne meurt pas car il se trouve sur le segment de mémoire, pas sur la pile. Cependant, si vous allouez quelque chose sur la pile et que vous le retournez, ce serait une mauvaise chose. Par exemple, l'un ou l'autre serait très mauvais:

int *myBadAddingFunction(int a, int b)
{
    int result;

    result = a + b;
    return &result; // this is very bad and the result is undefined
}

char *myOtherBadFunction()
{
    char myString[256];

    strcpy(myString, "This is my string!");
    return myString; // also allocated on the stack, also bad
}

Juste pour un peu plus d'explication orientée modèle de mémoire: quand une fonction est appelée, un espace temporaire est créé pour que la fonction mette ses variables locales, appelées frame . Lorsque la fonction (appelée) renvoie sa valeur, elle la place dans le cadre de la fonction qui l'a appelée (appelant), puis la trame appelée est détruite.

Le " cadre est détruit " Une partie est pourquoi vous ne pouvez pas renvoyer des pointeurs ou des références à des variables locales à partir de fonctions. Un pointeur est en réalité un emplacement de mémoire. Par conséquent, le renvoi de l'emplacement de mémoire d'une variable locale (par définition: une variable dans le cadre) devient incorrect une fois le cadre détruit. Étant donné que le cadre appelé est détruit dès qu'il renvoie sa valeur, tout pointeur ou référence à une variable locale est immédiatement incorrect.

La variable locale est copiée dans la valeur de retour. Les constructeurs de copie sont appelés pour les classes non triviales.

Si vous renvoyez un pointeur ou une référence à une variable locale, vous rencontrerez des difficultés, comme suggéré par votre intuition.

Cela dépend du type d'élément renvoyé. Si vous renvoyez par valeur, une nouvelle copie de la variable est créée pour être renvoyée à l'appelant. Je pense que vous n’aurez pas besoin de vous soucier de la durée de vie d’un objet, mais du coût de la copie d’objets (mais veuillez ne pas l’optimiser prématurément - la correction est beaucoup plus importante):

std::string someFunc( std::string& const s)
{
    return s + "copy";
}

Si la fonction renvoie une référence, vous devez faire attention à ce que vous retournez, car sa durée de vie doit s'étendre au-delà de la durée de vie de la fonction et l'appelant ne sera pas nécessairement en mesure de supprimer . si vous utilisez new pour créer l'objet:

std::string& someFunc2( std::string const& s)
{
    return s + "reference to a copy";   // this is bad - the temp object created will 
                                        //  be destroyed after the expression the 
                                        //  function call is in finishes.
                                        //  Some, but not all, compilers will warn 
                                        //  about this.
}

Bien sûr, les pointeurs renvoyés auront des considérations de durée de vie similaires.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top