Static variables in member functions

101,644

Solution 1

Since class A is a non-template class and A::foo() is a non-template function. There will be only one copy of static int i inside the program.

Any instance of A object will affect the same i and lifetime of i will remain through out the program. To add an example:

A o1, o2, o3;
o1.foo(); // i = 1
o2.foo(); // i = 2
o3.foo(); // i = 3
o1.foo(); // i = 4

Solution 2

The keyword static unfortunately has a few different unrelated meanings in C++

  1. When used for data members it means that the data is allocated in the class and not in instances.

  2. When used for data inside a function it means that the data is allocated statically, initialized the first time the block is entered and lasts until the program quits. Also the variable is visible only inside the function. This special feature of local statics is often used to implement lazy construction of singletons.

  3. When used at a compilation unit level (module) it means that the variable is like a global (i.e. allocated and initialized before main is run and destroyed after main exits) but that the variable will not be accessible or visible in other compilation units.

I added some emphasis on the part that is most important for each use. Use (3) is somewhat discouraged in favor of unnamed namespaces that also allows for un-exported class declarations.

In your code the static keyword is used with the meaning number 2 and has nothing to do with classes or instances... it's a variable of the function and there will be only one copy of it.

As correctly iammilind said however there could have been multiple instances of that variable if the function was a template function (because in that case indeed the function itself can be present in many different copies in the program). Even in that case of course classes and instances are irrelevant... see following example:

#include <stdio.h>

template<int num>
void bar()
{
    static int baz;
    printf("bar<%i>::baz = %i\n", num, baz++);
}

int main()
{
    bar<1>(); // Output will be 0
    bar<2>(); // Output will be 0
    bar<3>(); // Output will be 0
    bar<1>(); // Output will be 1
    bar<2>(); // Output will be 1
    bar<3>(); // Output will be 1
    bar<1>(); // Output will be 2
    bar<2>(); // Output will be 2
    bar<3>(); // Output will be 2
    return 0;
}

Solution 3

Static variables inside functions

  • Static variable is created inside a function is stored on program’s static memory not on the stack.

  • Static variable initialization will be done on the first call of the function.

  • Static variable will retain the value in multiple function calls

  • Lifetime of the static variable is Program

enter image description here

Examples

#include <iostream>

using namespace std;

class CVariableTesting 
{
    public:
    
    void FuncWithStaticVariable();
    void FuncWithAutoVariable();

};

void CVariableTesting::FuncWithStaticVariable()
{
    static int staticVar = 0; //staticVar is initialised by 0 the first time
    cout<<"Variable Value : "<<staticVar<<endl;
    staticVar++;
}
void CVariableTesting::FuncWithAutoVariable()
{
    int autoVar = 0;
    cout<<"Variable Value : "<<autoVar<<endl;
    autoVar++;
}
    

int main()
{
    CVariableTesting objCVariableTesting;
    cout<<"Static Variable";
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    
    cout<<endl;
    cout<<"Auto Variable";
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    
    return 0;
}

Output :

Static Variable

Variable Value : 0
Variable Value : 1
Variable Value : 2
Variable Value : 3
Variable Value : 4

Auto Variable

Variable Value : 0
Variable Value : 0
Variable Value : 0
Variable Value : 0
Variable Value : 0

Share:
101,644

Related videos on Youtube

monofonik
Author by

monofonik

MERGE KEEP

Updated on June 27, 2020

Comments

  • monofonik
    monofonik almost 4 years

    Can someone please explain how static variables in member functions work in C++.

    Given the following class:

    class A {
       void foo() {
          static int i;
          i++;
       }
    }
    

    If I declare multiple instances of A, does calling foo() on one instance increment the static variable i on all instances? Or only the one it was called on?

    I assumed that each instance would have its own copy of i, but stepping through some code I have seems to indicate otherwise.

  • 6502
    6502 almost 13 years
    No. Globals are initialized at program startup, function statics are initialized at first use. This is a big difference.
  • 0xbadf00d
    0xbadf00d almost 13 years
    I don't think this is what happens. However, this should be compiler specific anyway.
  • 6502
    6502 almost 13 years
    Then you think wrong: 3.6.1 in the C++ standard dictates that construction of object of namespace scope with static storage duration happens at startup; 6.7 (4) dictates that in general "... such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization". By the way this initialization-on-first-use is very handy to implement lazy singleton construction.
  • 0xbadf00d
    0xbadf00d almost 13 years
    3.7.4: "Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered. An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is initialized the first time control passes through its declaration;"
  • 0xbadf00d
    0xbadf00d almost 13 years
    So, I don't think I'm wrong. I don't know wheter we are talking about the same thing or not. You're right in a case where constant initialization is not possible. Then "such a variable is initialized the first time control passes through its declaration;".
  • 6502
    6502 almost 13 years
    I'm not sure if you really don't get it or if you just like to fight for some reason I don't understand. Of course if your program cannot tell if the initialization could have been done before then the implementation is free to do that before (but then again how can you tell it did it before?). If on the other side you're in the only interesting case to discuss, i.e. you can tell the difference because for example your static is an instance of a class and constructor has side effects then it MUST be done the first time the block is entered.
  • 0xbadf00d
    0xbadf00d almost 13 years
    I've never said anything other than that. I was just speaking of constant initialization.
  • 6502
    6502 almost 13 years
    Curiously enough however: 1) for constant initialization it's irrelevant discussing if a local static can be initialized before entering the block the first time (the variable is only visible inside the block and constant initialization produces no side effects); 2) nothing in your post is said about constant initialization; 3) local statics are very useful for non-constant initialization like MyClass& instance(){ static MyClass x("config.ini"); return x; } - a valid portable implementation for single-thread use exactly because local statics are NOT simply like a global despite what you say.
  • Stingery
    Stingery about 10 years
    Thanks for the good example! Would there be a way to actually achieve something that makes the scope of static int i specific to the instance, so that e.g. o1.foo(); // i = 1 and $o2.foo(); // i = 1 ...?
  • Carl Morris
    Carl Morris over 9 years
    Although this may not be the style you are looking for, making i a private data member of class A would have the effect you are describing. If you are concerned about name conflicts, you could add a prefix such as m_ to indicate the status of i.
  • austinmarton
    austinmarton over 8 years
    Anyone got a reference for "somewhat discouraged in favor of unnamed namespaces"?
  • 6502
    6502 over 8 years
    @austinmarton: The phrase "The use of static to indicate 'local to translation unit' is deprecated in C++. Use unnamed namespaces instead (8.2.5.1)" is present on The C++ Programming Language in my edition (10th print, September 1999) at page 819.
  • ytobi
    ytobi almost 4 years
    Please, mention what happens if the class and method are templatized.
  • iammilind
    iammilind almost 4 years
    @ytobi, in such case for every instance of the templated method of a normal/template class, a separate static variable will be created. That variable will be applicable only to those types. e.g. template<typename T> void foo (T t) {...}. Now for foo<int> there will be a static int i (say foo<int>::i) and separate for foo<string> there will be a separate static int i (say foo<string>::i) and so on. i will be incremented separately for foo<int> than from the foo<string>. Hope that clears the doubt.
  • Andrew
    Andrew over 3 years
    @iammilind (& OP) static does indeed have a few different meanings; however, I fail to see how saying those meanings are "unrelated" is justified. It always means, "Have only one of these per <context>, which transcends <context>."
  • Andrew
    Andrew over 3 years
    To clarify, you'd need to set i = 0; in the OP's code in order to get this result.
  • 6502
    6502 over 3 years
    @Andrew: static at compilation unit level means the opposite (it means "local to compilation unit")
  • iammilind
    iammilind over 3 years
    @Andrew, with standard conforming compilers, static variables are value initialised to 0 by default.
  • Andrew
    Andrew over 3 years
    Why? . . . . . .
  • fde-capu
    fde-capu about 3 years
    Would "address" be a better word choice instead of "value"? The value changes, it is not a const.
  • Saurabh Raoot
    Saurabh Raoot about 3 years
    Yes. We can show it with address as well.
  • fde-capu
    fde-capu about 3 years
    I mean, instead of "Static variable will retain the value in multiple function calls" -> "Static variable will retain the memory address in multiple function calls (even if its value changes)".
  • Eugene
    Eugene over 2 years
    What will happen if the function is defined in-class and the class definition is included multiple times in and across libraries, will it still remain one in a program?
  • 463035818_is_not_a_number
    463035818_is_not_a_number almost 2 years
    @austinmarton rather old comment, but by chance i came across this yesterday: open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1012. The commitee even considered to deprecate that use of static because unnamed namespaced. The linked report is about (among other things) keeping that use of static even though an unnamed namespace can achieve the same