Static variables in member functions
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++
When used for data members it means that the data is allocated in the class and not in instances.
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.
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 aftermain
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
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
Related videos on Youtube
Comments
-
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 callingfoo()
on one instance increment the static variablei
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 almost 13 yearsNo. Globals are initialized at program startup, function statics are initialized at first use. This is a big difference.
-
0xbadf00d almost 13 yearsI don't think this is what happens. However, this should be compiler specific anyway.
-
6502 almost 13 yearsThen 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 almost 13 years3.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 almost 13 yearsSo, 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 almost 13 yearsI'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 almost 13 yearsI've never said anything other than that. I was just speaking of constant initialization.
-
6502 almost 13 yearsCuriously 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 about 10 yearsThanks 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 over 9 yearsAlthough 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 over 8 yearsAnyone got a reference for "somewhat discouraged in favor of unnamed namespaces"?
-
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 almost 4 yearsPlease, mention what happens if the class and method are templatized.
-
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 forfoo<int>
there will be astatic int i
(sayfoo<int>::i
) and separate forfoo<string>
there will be a separatestatic int i
(sayfoo<string>::i
) and so on.i
will be incremented separately forfoo<int>
than from thefoo<string>
. Hope that clears the doubt. -
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 over 3 yearsTo clarify, you'd need to set
i = 0;
in the OP's code in order to get this result. -
6502 over 3 years@Andrew:
static
at compilation unit level means the opposite (it means "local to compilation unit") -
iammilind over 3 years@Andrew, with standard conforming compilers, static variables are value initialised to 0 by default.
-
Andrew over 3 yearsWhy? . . . . . .
-
fde-capu about 3 yearsWould "address" be a better word choice instead of "value"? The value changes, it is not a const.
-
Saurabh Raoot about 3 yearsYes. We can show it with address as well.
-
fde-capu about 3 yearsI 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 over 2 yearsWhat 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 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