C++ code while returning reference to integer - c++

I tried the following piece of code:
int& fun()
{
static int y = 20;
//y = 40;
return y;
}
int main()
{
fun() = 30;
cout << fun() <<endl;
return 0;
}
If, line y = 40 were uncommented, output of main is 40. Why doesn't the value of y change when it's assigned to 30 in main() ?

The variable y of the function func() has static storage duration:
3.7.1/1: All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static
storage duration. The storage for these entities shall last for the
duration of the program
3.7.1/3: The keyword static can be used to declare a local variable with static storage duration.
The initialisation of such variables occurs only once. This means that the first time you use y its value is 20, afterwards it keeps the value that you store there in.
Case 1: assignment is commented out:
The statement fun() = 30; will store 30 in y. cout << fun() will use the reference to y without fun() changing it, so it will display 30.
Case 2: assignment is activated:
The statement fun() = 30; will store 30 in y. cout << fun() will use the reference to y but fun() will first set it to 40, so 40 will be displayed.

Related

Static variable used in a template function

I am not able to understand the output of the below code:-
#include <iostream>
using namespace std;
template <typename T>
void fun(const T&x){
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
int main(){
fun(1);
fun('A');
fun(1.1);
fun(2.2);
return 0;
}
Output:-
x = 1 count = 0
x = A count = 0
x = 1.1 count = 0
x = 2.2 count = 1
If value of static variable count is being reassigned to 0 whenever the function is called, then why its coming 1 when the function is being called fourth time.
And another thing , can we not pass "T x" directly instead of "const T&x"?
When a template gets instantiated, with explicit or deduced template parameters, it's as if a completely new, discrete, class or function gets declared. In your case, this template ends up creating three functions:
void fun<int>(const int &x)
void fun<char>(const char &x)
void fun<double>(const double &x)
It's important to understand that each one of these is a separate, standalone function, with its own static count variable. Because it's static, it gets initialized once, and its value is preserved across function calls. That's how static variables work in functions.
The shown code calls the first two once, and the third one twice. Those are the results you are seeing (the 2nd call to the third function incremented the same static count again).
Templates in C++ aren't generic functions like they are in Java. They're more like cookie cutters that make a new type-specific function for each type used to instantiate them. Your code is basically equivalent to this:
#include <iostream>
using namespace std;
void fun_int(const int&x){
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
void fun_char(const char&x){
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
void fun_double(const double&x){
static int count = 0;
cout << "x = " << x << " count = " << count << endl;
++count;
return;
}
int main(){
fun_int(1);
fun_char('A');
fun_double(1.1);
fun_double(2.2);
return 0;
}
And now it's obvious that you don't just have one static variable, but rather three different ones in different functions that just happen to have the same name.
If value of static variable count is being reassigned to 0 whenever the function is called...
That's where you're wrong. A static variable with an initializer (irrespective of its scope) is set to the value of the initializer once and once only. For static variables declared globally (in file scope), that initialization will be at program start-up; for static data declared in functions (as yours are), that initialization is deferred to the first time the function's code is executed.
Your code defines three different overloads of fun, each of which has its own copy of the local count variable. When the overload with the double argument is called the second time, the count variable will not be reinitialized – just incremented.
From this Draft C++17 Standard:
6.8.3.2 Static initialization     [basic.start.static]
1    Variables with static storage duration are initialized as a consequence of program
initiation. …
and, for locally-declared static variables, we have this:
9.7 Declaration statement     [stmt.dcl]
…
4    Dynamic initialization of a block-scope variable
with static storage duration or thread storage
duration is performed the first time control passes through its
declaration; such a variable is considered initialized upon the completion of its initialization. …

How does this piece of C++ code work?

I saw this below example in Geek For Geeks.
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Answer is 30.
But i am unable to map, how this value is arrived at. Please help me as to how this piece of code works.
After some answers from experts, i got to know the value assigned to function is assigned to static variable x which is equivalent to fun()::x =30
Now, i tried a different piece of code.. where in i have 2 static variables inside the fun() and returning the second variable reference. Still the answer is 30. Is is because when, fun() is assigned, it assigns the value 30 to all the variables inside fun()?
Second piece of code is
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
static int y =20;
return y;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
fun returns a reference (int&) to the static variable x inside funs scope. So essentially the statement fun() = 30 is fun::x = 30. Note this is only safe because x is static.
function local static variables get initialized the first time into the function and persist until the end of the program. So when you call
fun() = 30;
You return a reference to that variable and then assign 30 to it. Since the variable is still alive it will keep that value. Then
cout << fun();
Is going to return the variable again. Since it was already initialized it will not reset its value and it returns 30 as that is what it was set to in the preceding line.

On local and global static variables in C++

C++ Primer says
Each local static variable is initialized before the first time
execution passes through the object's definition. Local statics are
not destroyed when a function ends; they are destroyed when program
terminates.
Are local static variables any different from global static variables? Other then the location where they are declared, what else is different?
void foo () {
static int x = 0;
++x;
cout << x << endl;
}
int main (int argc, char const *argv[]) {
foo(); // 1
foo(); // 2
foo(); // 3
return 0;
}
compare with
static int x = 0;
void foo () {
++x;
cout << x << endl;
}
int main (int argc, char const *argv[]) {
foo(); // 1
foo(); // 2
foo(); // 3
return 0;
}
The differences are:
The name is only accessible within the function, and has no linkage.
It is initialised the first time execution reaches the definition, not necessarily during the program's initialisation phases.
The second difference can be useful to avoid the static intialisation order fiasco, where global variables can be accessed before they're initialised. By replacing the global variable with a function that returns a reference to a local static variable, you can guarantee that it's initialised before anything accesses it. (However, there's still no guarantee that it won't be destroyed before anything finishes accessing it; you still need to take great care if you think you need a globally-accessible variable. See the comments for a link to help in that situation.)
Their scope is different. A global-scoped static variable is accessible to any function in the file, while the function-scoped variable is accessible only within that function.
Hopefully, this example will help to understand the difference between static local and global variable.
#include <iostream>
using namespace std;
static int z = 0;
void method1() {
static int x = 0;
cout << "X : " << ++x << ", Z : " << ++z << endl;
}
void method2() {
int y = 0;
cout << "Y : " << ++y << ", Z : " << ++z << endl;
}
int main() {
method1();
method1();
method1();
method1();
method2();
method2();
method2();
method2();
return 0;
}
output:
X : 1, Z : 1
X : 2, Z : 2
X : 3, Z : 3
X : 4, Z : 4
Y : 1, Z : 5
Y : 1, Z : 6
Y : 1, Z : 7
Y : 1, Z : 8
There real name is:
static storage duration object.
Global variables are also 'static storage duration object'. The major difference from global variables are:
They are not initialized until the first use
Note: An exception during construction means they were not initialized and thus not used.
So it will re-try the next time the function is entered.
Their visability is limited by their scope
(ie they can not be seen outside the function)
Apart from that they are just like other 'static storage duration objects'.
Note: Like all 'static storage duration objects' they are destroyed in reverse order of creation.
The main or most serious difference is time of initialization. Local static variables are initialized on first call to function where they are declared. The global ones are initialized at some point in time before the call to main function, if you have few global static variables they are intialized in an unspecified order, which can cause problems; this is called static initialization fiasco.
In your first code block, x is local to the foo() function which means that it is created in foo() and destroyed at the end of the function after cout. However, in your second block x is global which means that the scope of x is the entire program. If you wanted to under int main your could cout << x << endl and it would print however, in the first block it would say x not declared
They are known to all functions in a program whereas global
variables are known only in a limited scope.
Global static variables can be initialized before the program starts whereas local static variables can be initialized as execution reaches point.

C++: Static variable declarations in a function

Static variables exist outside of the function, in terms of their memory at least (not scope), right? But one thing that always concerned me, is what happens when I call the function a second time. For instance:
f(){
static char buffer[256*256];
stuff(buffer);
}
When I call this function a second time, wouldn't it technically be declaring the variable 'buffer' a second time? Or does it work differently with static variables (as opposed to normal ones) once everything is compiled?
... I sometimes wish there was a chart or something of what a c++ compiler usually turns code into (minus optimizations) so I wouldn't have to bother you fine folks with little questions like this, aha. Thank you in advance!
edit: I know it works like this, I just want to know why though. It's probably something mind numbingly simple...
Static storage duration objects in function scope.
These objects are created on first use.
Then destroyed in reverse order of creation (with other static storage duration objects).
#include <iostream>
class X
{
public:
X(int x): m(x) {std::cout << "X: " << m << " created\n"; }
~X() {std::cout << "X: " << m << " destroyed\n";}
private:
int m;
};
static X x1(1);
int test()
{
std::cout << "Test: Start\n";
static X x3(3);
std::cout << "Test: Finished\n";
return 5;
}
int main()
{
std::cout << "Main: Start\n";
X x2(2);
test();
X x4(4);
std::cout << "Main: Finished\n";
}
Now Try it: (comments added). SSDO => Static Storage Duration object.
g++ X.cpp
./a.out
X: 1 created // SSDO file scope.
Main: Start
X: 2 created
Test: Start
X: 3 created // SSDO created on first use (Notice not destroyed)
Test: Finished
Test: Start // Notice not created here.
Test: Finished
X: 4 created
Main: Finished
X: 4 destroyed
X: 2 destroyed // Main now really finished. after destroying local variables.
X: 3 destroyed // Destroy SSDO in reverse order of creation. (3 - 1)
X: 1 destroyed
No, you static means that it is outside the scope of your function. It has the same effect as writing:
static char buffer[256*256];
f(){
stuff(buffer);
}
Except that the buffer is only visible in the scope of your function, and the code is more readable.
(NOTE: My example doesn't apply when char is not a primitive type - in that case, it is constructed the first time it is "declared").
In this context, static means that the variable has application lifetime. It is allocated before main() the function is entered, and deallocated after main() has returned. Also, its value is preserved between function calls. Think of it as a global variable that is only visible from inside that function.
The variable exists before and after you call the function...it's static.
This example might illustrate it:
#include <iostream>
using namespace std;
void test() {
static int i = 123;
if (i == 123) {
i = 321;
}
cout << i << endl;
}
int main(int arg, char **argv) {
test();
test();
return 0;
}
The output is:
321
321
So "i" is only initialized the first time it is encountered, so to speak. But actually it's allocated at compile time for that function. Afterwards, it's just in the scope of the function test() as a variable, but it is static so changing it changes it in all future calls to test() as well.

Static variables in C++

I ran into a interesting issue today. Check out this pseudo-code:
void Loop()
{
static int x = 1;
printf("%d", x);
x++;
}
void main(void)
{
while(true)
{
Loop();
}
}
Even though x is static, why doesn't this code just print "1" every time? I am reinitializing x to 1 on every iteration before I print it. But for whatever reason, x increments as expected.
The initialization of a static variable only happens the first time. After that, the instance is shared across all calls to the function.
I am reinitializing x to 1 on every iteration
No, you're not: you're initializing it to 1, but it only gets initialized once.
static doesn't mean const.
From MSDN:
When modifying a variable, the static
keyword specifies that the variable
has static duration (it is allocated
when the program begins and
deallocated when the program ends) and
initializes it to 0 unless another
value is specified. When modifying a
variable or function at file scope,
the static keyword specifies that the
variable or function has internal
linkage (its name is not visible from
outside the file in which it is
declared).
A variable declared static in a
function retains its state between
calls to that function.
When modifying a data member in a
class declaration, the static keyword
specifies that one copy of the member
is shared by all instances of the
class. When modifying a member
function in a class declaration, the
static keyword specifies that the
function accesses only static members.
The value of static is retained between each function call, so for example (from MSDN again):
// static1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void showstat( int curr ) {
static int nStatic; // Value of nStatic is retained
// between each function call
nStatic += curr;
cout << "nStatic is " << nStatic << endl;
}
int main() {
for ( int i = 0; i < 5; i++ )
showstat( i );
}
In your example, x will increment as expected because the value is retained.
static in this context means that value should be retained between calls to the function. the initialization is done only once.