I recently read about references in C++. I am aware of basic properties of references but I am still not able to figure out why following two programs produce different output.
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
This program prints 30 as output. As per my understanding, the function fun() returns a reference to memory location occupied by x which is then assigned a value of 30 and in the second call of fun() the assignment statement is ignored.
Now consider this program:
#include<iostream>
using namespace std;
int &fun()
{
int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
This program produces the output as 10. Is it because, after the first call, x is assigned 30, and after second call it is again overwritten to 10 because it is a local variable? Am I wrong anywhere? Please explain.
In the first case, fun() returns a reference to the same variable no matter how many times you call it.
In the second case, fun() returns a dangling reference to a different variable on every call. The reference is not valid after the function returns.
When you use
fun() = 30;
in the second case, you are setting the value of a variable that is not valid any longer. In theory, that is undefined behavior.
When you call fun() the second time in the second case, the variable x is set to 10. That is independent of the first call to the same function.
Just adding to what has been said. The reason behind the first case's behavior is because it is a static variable, which has a static duration. Static duration means that the object or variable is allocated when the program starts and is deallocated when the program ends.
This means that once x in the first case has been initialized the first time with 10, the next function call will ignore static int x = 10; because x cannot be instantiated again, as it has already been allocated, and will simply proceed to return x;, which will be the same x that was assigned 30 in main.
Basically, your understanding is right, except for in 2nd case, you're processing a dangled reference of the local variable has been invalid, which is undefined behaviour, means anything is possible. What you said is just one of the possibility, it also could result in others, such as getting a random number, program crash, etc.
Related
I've made this example to show what I'm talking about. I want to know if there is a way to run through main() without resetting value to 0.
int main(){
int value = 0;
value++;
cout << value << endl;
main();
}
Before answering the question, your example has two big problems
Calling, or even taking the address of, main is not allowed.
Your function has infinite recursion which makes your program have undefined behavior.
A different example where value is saved between calls could look like this. It uses a static variable, initialized to 0 the first time the function is called, and is never initialized again during the program execution.
#include <iostream>
int a_function() {
static int value = 0;
++value;
if(value < 100) a_function();
return value;
}
int main(){
std::cout << a_function(); // prints 100
}
If you want to keep the variable value local to the main function, you can declare it as static int value = 0;.
As has been pointed out in various comments though, recursively calling any function without an escape mechanism like you are is a bad idea. Doing it with main is a worse idea still apparently not even possible.
Can we have a function calling at the left side of the expression?
This code snippet works well but how? How can a function calling can be at left side and please elaborate how this snippet is executing and working well and what if i wouldn't have used static int in function definition.Thanks in advance.
#include<iostream>
using namespace std;
int &fun()
{
static int x;
return x;
}
int main()
{
fun() = 10;
/* this line prints 10 on screen */
printf(" %d ", fun());
getchar();
return 0;
}
Any expression that returns a non-const lvalue can be on the left side of the assignment and function call is also an expression like any other. Since lvalue historically means exactly that - value on the left side this turns into a recursive definition. So instead you can consider an lvalue anything that you can take address of:
int x = 5;
&x; //valid, takes the address of the variable
&5; //invalid, integer literal has no address
int func1();
&func1(); //invalid, can't take the address of the temporary value
int &func2();
&func2(); //valid, since the function returned reference
//which itself is almost the same as the address
So any expression that results in something addressable can be assigned to. You can even do something like this:
int x = 0;
int y = 0;
int z = 5;
(z > 5 ? x : y) = 10;
As for your second question, if you remove static from your function you would return a reference to a local variable of the function. Local variables stop existing when the function exits, so you would return a reference to a variable that is already destroyed. This, however, will compile and run, but the results of that execution would be unpredictable that's why this is called undefined behavior.
This seemed to be the closest; my program is similar, but my question is slightly different.
I'm having trouble seeing why the output of this program is "5,5" instead of "5,4". I was under the impression that the value "4" was immediately assigned to the "static float" variable "m" once the maxvalue function was called.
If that is the case, why is 5 the output instead of 4?
#include <iostream>
using namespace std;
float keepmax(float f) {
static float m = f;
if(f>m)
m = f;
return m;
}
int main() {
cout << keepmax(5) << endl;
cout << keepmax(4) << endl;
return 0;
}
In C++, a static variable declared within a function scope will be created and initialized once for all non-recursive calls to that function.
NOTE: Recursive calls effect on static variable initializations are undefined behavior according to the C++ standard.
C++ Standard 6.7 Paragraph 4:
If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
Example:
int foo(int i) {
static int s = foo(2*i); // recursive call - undefined
return i+1;`
}
The first time your function enters the keepmax function, your static float m variable is initialized to the value passed in, which in this case is 5. From this point on, the variable has been created and initialized and the static float m = f; statement will, in essence, be skipped over.
The second time your function enters keepmax, m still has the value 5 from the first call, and the execution (essentially) "jumps over" the static float m = f; statement and goes directly to the comparison. Because m equals 5 and f equals 4, the comparison (f>m) is false (as 4 is not greater than 5), and the subsequent assignment never occurs.
I was under the impression that the value "4" was immediately assigned to the "static float" variable "m" once the maxvalue function was called.
You where under wrong impression, that is not assignment but initialization, and it only happens once when execution flow goes through that code the first time, that's how local static variables work. If you want that variable to change value every time, you need to make it non static:
float m = f;
or you can also make assignment happen every time:
static float m;
m = f;
but then it does not make any sense to make this variable static (unless this assignment is done conditionally)
Because the static will continue holding its value even after the function has returned. Hence when you call it the second time, it still retained '5' as the highest value.
Could anyone please elaborate the behaviour of reference in this code and why is it printing 12 in first line instead of 11.
Below is the code
http://ideone.com/l9qaBp
#include <cstdio>
using namespace std;
int &fun()
{
static int x = 10;
x++;
return x;
}
int main()
{
int *ptr=&fun();
int *ptr1=&fun();
printf("%p %p \t %d %d",(void*)ptr,(void*)ptr1,*ptr,*ptr1);
return 0;
}
the output of the code is
134519132 134519132 12 12
Please explain why 12 is getting printed on first call not 11 i understand when second call is made it should print 12
ptr and ptr1 are pointing to the same variable static int x. The second call changed the value of static int x to 12, then you print out the value by derefernce ptr and ptr1, the same result will be printed out.
The int reference returned by fun() is the same for both calls (ref to the static x), hence the address of that reference is the same for both calls. Hence the resulting dereference of that identical address is the current identical value.
Your error seems to be in thinking that printf() prints *ptr as soon as it comes available. It does not; printf() is not called until both ptr and ptr1 are computed. Since both ptr and ptr1 point to the same memory location, which is a static variable, and that location is updated after both the first call to fun() and the second, the address holds that value.
static variables have lifetime extent and are stored in statically allocated memory. It means that the storage of static local variables inside a function is not allocated and deallocated on call-stack.
Once x is initialized at compile time, the value of x is kept stored between the invocations of function fun.
As C++ statements are executed sequentially, printf will be executed after the invocations of two function calls in the given lines
int *ptr=&fun();
int *ptr1=&fun();
and therefore the value of x will be 12 before the execution of printf statements.
Keep in mind that
int *ptr=&fun();
int *ptr1=&fun();
is not equivalent to
int& (*ptr)() = &fun;
int& (*ptr1)() = &fun;
In second snippet ptr and ptr1 both holding the address of function fun. In this case you need to call function directly or by using these pointers as
int a = ptr();
int b = ptr1();
after this invocation value of a and b will be 12.
I have come across a sample source code regarding use reference data member and i am confused about output. Here is sample code.
class Test {
private:
int &t;
public:
Test (int y):t(y) { }
int getT() { return t; }
};
int main() {
int x = 20;
Test t1(x);
cout << t1.getT() << "\n"; // Prints 20 as output. however y has already been destroyed but still prints 20.
x = 30;
cout << t1.getT() << endl; // Prints Garbage as output Why ? Ideally both steps should be Garbage.
return 0;
}
And to add for more confusion here is one more piece of code for same class
int main() {
int x = 20;
int z = 60;
Test t1(x);
Test t2(z);
cout<<t1.getT()<<"\n"; // Prints 60! WHY? Should print garbage
cout<<t2.getT() << "\n"; // Prints Garbage
cout<<t1.getT() << endl; // Prints Same Garbage value as previous expression
return 0;
}
x is passed by value using a temporary, so t is a reference to that temporary, not x. That temporary will be destroyed after constructor returns. Your code has undefined behavior. anything can come up as output. Your problem can be solved by passing a reference to x like
Test (int& y):t(y);
but this is not a good idea. There can be cases where x goes out of scope but the Test object is still used , then the same problem will appear.
Your constructor:
Test (int y):t(y) { }
sets t to be a reference to y, the local (temporary) variable on the stack, and not the variable in the calling function. When you change the variable value in the calling function it does not change anything in the object you created.
The fact that the reference is to a temporary variable that is lost at the end of the life of the constructor means that getT() returns an undefined value.
Every call to int getT() accesses the memory address for y. That memory address was released from the stack at the end of the constructor, so it points to memory that is not on the stack or the heap and so may be reused at any time. The time of reuse is not defined and depends on other operations established by the compiler and dependency libraries. The return value of int getT() therefor depends on other elements on your OS that affect memory, the compiler type and version, and the OS amongst other things.
Now i got it. Yes it is undefined but to answer my question why it is printing 20 or 60 before printing garbage? Actually answer is that 20 and 60 both values are garbage and ideally both getT function calls should print Garbage but it doesn't.Because there is no other instruction between Test t2(z);
cout<<t1.getT()<<"\n";
but for next statement \n works as a instruction and meanwhile stack clears the value.