enzom83
enzom83

Reputation: 8310

What is the utility of declaring a static variable in function?

What is the pratical utility of declaring a static variable in function? I understood the lifetime of a static variable declared within a function, but I can not figure a practical example where it might be useful (or necessary) to declare a static variable in a function. Could you give me an example of a problem that should be solved in this way?

Upvotes: 4

Views: 248

Answers (7)

Yirkha
Yirkha

Reputation: 13828

Adding to other answers, you also need to remember that in C++, the static keyword has many meanings. In a function body, it also changes that a variable is not to be created on stack, but only once in global memory, and with a const modifier and initialized with a compile-time constant, they can even be put away nicely into the read-only section.

This is commonly used for local definitions of arrays or strings:

static const int indices[] = {1, 3, 5, 7, ...};
for (int index : indices) {
   // do something
}

static const char sqlCommand[] = "INSERT INTO ... some long statement ...";
if (!m_database.prepare(sqlCommand, ...)) {
   m_log.error("Error preparing query: %s", sqlCommand);
   // ...
}

If static wasn't there, the compiler would needlessly construct the array or string on the stack each time, value by value [1].

This is often used with lookup tables, repeated string constants (more manageable this way than macros), packet payloads etc. and the practical problem it solves is better performance and smaller code size.

[1] Almost, compilers are good at optimizing this stuff nowadays.

Upvotes: 2

rcgldr
rcgldr

Reputation: 28826

A simpler example would be a variable that counts how many times a function has been called:

void foo()
{
static int count;
// ...
count++;
// ...
}

Since it's declared static, it's initialized to zero only once, at program load time. This is different than

static int count = 0;

in which case it would be set to zero each time the function was called.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206607

It allows you to create static data only once during the life of the process and use it through out the life of the process.

Example 1

Say you have a function that returns a long unit name given a short unit name. Given "m" as a unit, you would like to get back "meter". You can keep a map as a static variable in the function.

std::string const&  getLongName(std::string const& shortName)
{
   static std::map<std::string, std::string> unitsmap;
   static std::string unknownUnit("Unknown Unit");
   if ( unitsmap.empty() )
   {
       unitsmap["m"] = "meter";
       unitsmap["cm"] = "centimeter";
       unitsmap["mm"] = "millimeter";
       unitsmap["g"] = "gram";
       unitsmap["kg"] = "kilogram";

       // etc.
   }
   std::map<std::string, std::stirng>::iterator f = unitsmap.find(shortName);
   if ( f != unitsmap.end() )
   {
      return f->second;
   }
   else
   {
      return unknownUnit;
   }
}

Example 2

The simple implementation of the Singleton Pattern can use a static variable in a function.

class Singleton
{
   public:
      static Singleton* instance()
      {
        static Singleton* theInstance = NULL;
        if ( theInstance == NULL )
        {
           theInstance = new Singleton;
        }
        return theInstance;
     }

  private:
     Singleton() {}
};

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

By declaring a static variable in a function, you

  • limit the variable's scope, and

  • delay dynamic initialization to the first time execution passes through the declaration.

In some cases the limited scope is most important, e.g. for a local constant.

In other cases the delayed dynamic initialization is the most important, e.g. for a Meyers' singleton.


One practical use case is to define a constant of arbitrary type with effectively external linkage (so that it won't be duplicated in each translation unit), in a header file, like

inline
auto get_t()
    -> T const&
{
    static T const the_t;
    return the_t;
}

T const& t = get_t();

Here the reference takes up minimum space.

This can however also be done via the "templated constant" trick, or in C++11 via constexpr, if applicable.

For comparison, here's the same as the above expressed with the "templated constant" trick (again, the purpose is to provide the extern linkage constant in a header file):

template< class Dummy >
struct The_t_constant
{
    static T const value;
};

template< class Dummy >
T const The_t_constant<Dummy>::value;

T const& t = The_t_constant<void>::value;

Upvotes: 6

Flovdis
Flovdis

Reputation: 3095

A classic example is a delayed creation of a global instance of an object (not thread safe).

class Foo
{
    // ...
    static Foo* instance();
}

Foo* Foo::instance() {
    static Foo *obj = nullptr;
    if (obj == nullptr) {
        obj = new Foo();
        // ...
    }
    return obj;
}

Upvotes: 1

rerun
rerun

Reputation: 25505

The practical example is to create some default which is not a compile time constant. It also is better encapsulation because I don't expose the rest of my system to that static.

int DoSomething()
{
   static foo * myFoo = new foo();//foos constructor may read from the environment or whatever else 
                                  //I only need it the first time I call DoSomething if I never call DoSomthing its never created


}

Upvotes: 0

Alan Stokes
Alan Stokes

Reputation: 18964

Imagine the function needs some value which is very expensive to compute, doesn't vary, and may never be needed at all. So you want to compute it, once, when it is first needed but not before.

Upvotes: 3

Related Questions