Just started learning c and came across this example where the function is returning a reference to a local static variable.
int& fun() {
static int x = 10;
return x;
}
int main() {
int &z = fun();
cout << fun() << " ";
z = 30;
cout << fun();
return 0;
}
What does the line int &z = fun();
do? Are we storing a reference inside another reference? I'm new to the language and all I know is that reference variables refer to a variable just like an alias. Can anyone explain how this works?
CodePudding user response:
Are we storing a reference inside another reference?
No, references aren't even required to have "storage". A reference is something to simplify programming. auto& thing = foo.get_value_reference();
and then using thing
makes code easier to write and debug. thing
doesn't even have to exist as a separate entity when you look at the final assembly code.
int orig;
int& a = orig;
int& b = a;
b
is now a reference to orig
- nothing else. You can't reference a reference.
CodePudding user response:
Are we storing a reference inside another reference?
No, there is no reference to reference, at least in C\C .
For me, a reference is just a different name for another variable, at the end, they are all referring to the same, single object. In more detail, abstractly, whenever you write int& a = b
, all you have is still b
, and there is no such thing called a
, that ever exist. (a
is just an alias of b
)
Because of that, we can't have a different name of a name, that would sound a bit weird, since it does not actually refer to anything that exist.
In your case above, what int& fun()
does is returning the actual static int x = 10;
. And int &z = fun();
, once again, refer directly the the actual static int x = 10;
. Whatever z
or anything, afterall, it is just static int x = 10
, under different names.
This would be different if you remove the amphersand-&
to int fun()
, which returns a copied version of int x = 10;
, which means now existed two different things: int x = 10
and a copy of int x = 10
.
That's why C\C is memory-efficient, isn't it? You know when things get copied and when it does not, which helps optimization a lot!
Hope this helps!
CodePudding user response:
First of all, a variable declared static
inside a function is allocated when the program begins and deallocated when the program ends. We can keep a reference to it after returning from the function.
Let's consider this function:
int& fun() {
static int x = 10;
return x;
}
Returning a reference to the static variable x
is like returning the variable itself. This lets you increment it, for instance:
std::cout << func() << std::endl;
std::cout << func() << std::endl; # outputs 11
std::cout << func() << std::endl; # outputs 12
This is not possible if you're just returning the value of the variable.
int &z = fun()
lets you refer to that same static variable through the name z
in the same way:
int &z = fun();
std::cout << z << std::endl;
std::cout << z << std::endl; # outputs 11
std::cout << z << std::endl; # outputs 12
This idiom of having a function return a static variable (by reference or otherwise) can be used to guarantee when a "global" variable is initialized. The language guarantee that a static variable is initialized the first we pass through the declaration at runtime.
Let's consider:
int& fun() {
static int x = 10;
return x;
}
Here, init_x()
is called the first time we call fun()
to retrieve its value.
int& fun() {
static int x = init_x();
return x;
}