4

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?

asked Apr 16, 2014 at 22:01

7 Answers 7

6

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;
answered Apr 16, 2014 at 22:05
Sign up to request clarification or add additional context in comments.

1 Comment

It might be useful to point out that this technique (using get_t directly / Meyers' singleton) also avoids the static initialization order fiasco.
3

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.

answered Apr 16, 2014 at 22:05

Comments

2

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.

answered Apr 16, 2014 at 23:28

Comments

1

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;
}
answered Apr 16, 2014 at 22:10

Comments

1

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() {}
};
answered Apr 16, 2014 at 22:19

1 Comment

First example, probably want to put something into unknownUnit.
0

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
}
answered Apr 16, 2014 at 22:06

Comments

0

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.

answered Apr 16, 2014 at 23:32

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.