How to "clean" static variables?

Asked

Viewed 2,140 times

4

In C++ static variables are very important. Let’s assume that I want to make a factorial that uses recursion.

unsigned long long int RecursionFatorial(unsigned int fator)
{
    static long long int FatReturn;
    if(fator == 0)
    {
        unsigned long long int FatReturn_ = FatReturn;
        FatReturn = 0;
        return FatReturn_;
    }
    else
    {
        if(FatReturn == 0) FatReturn = 1;
        FatReturn *= fator;
        RecursionFatorial(fator - 1);
    }
}

The code runs and gives the expected result, but the code gets bigger: you need to create new variables (nonstatic) to reset the variables that are static, check if the new is zero to be able to change the value (first call) and cause unnecessary memory occupation. How we should make good use of static variables and then clean them?

  • In fact, this use you made of static variables is not recommended. If two threads call its function in parallel the result will not be set.

  • 3

    An interesting curiosity is that the reason FORTRAN 77 did not allow recursion is precisely because the local variables and the return value of the functions were stored in static locations instead of using the stack.

2 answers

10


A static variable (declared within a method) will keep its value between successive calls. If you don’t want to keep the value between successive calls, why not just use local (nonstatic) variables? Recursive factorial could be implemented more simply (including no local or static variables):

unsigned long long int RecursionFatorial(unsigned int fator)
{    
    if(fator == 0)
    {
        return 1;        
    }
    else
    {
        return fator * RecursionFatorial(fator - 1);
    }
}

5

If you need it, there’s something wrong with your design.

Static variables in functions should be used to store a state global, not a momentary state of operation.

First, you don’t need a state for a recursive function. You can use the return value directly:

unsigned long long fatorial(unsigned fator) {
    return fator == 0 ? 1 : fator * fatorial(fator-1);
}

Another common way is to use a parameter to save the state:

unsigned long long fatorial(unsigned fator, unsigned long long resultado = 1) {
    return fator == 0 ? resultado : fatorial(fator - 1, resultado * fator);
}

But if you insist on having a state, you can use an object. After all objects were made to have states:

struct Fatorial {
    unsigned long long resultado ;
    Fatorial() : resultado (1) {}
    unsigned long long calc(unsigned fator) {
        if (fator > 0) {
            resultado *= fator;
            calc(fator-1);
        }
        return resultado;
    }
}

Fatorial().calc(4) // 24

Note that it is a mess and is by far the ideal for a recursion.

Now answering the question of fact:

unsigned long long fatorial(unsigned fator, bool reset=true)
{
    static unsigned long long resultado;
    if (reset) resultado = 1;
    if (fator > 0) {
        resultado *= fator;
        fatorial(fator-1, false);
    }
    return resultado;
}
  • At the beginning: "Let’s assume I want to make a factorial[...]"

  • I didn’t understand. I assumed you were doing something similar to a factorial. What I said in my reply applies.

  • Yes, it’s correct. You said about the design, but it’s just an example ;)

  • Yes. But if you are using static variables for the state of recursive functions, whether or not factorial, there is something wrong with your design. Consider an alternative.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.