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.
Related
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?
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.
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!
First of all, a variable declared static inside a function is allocated when the program begins and deallocated when the program ends. Unlike normal local variables, it is safe to keep a reference to a static variable after returning from the function in which it is declared. It continues to exist and will keep its value.
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. We can increment the variable through that reference, for instance:
cout << fun()++ << endl;
cout << fun()++ << endl; // output: 11
cout << fun() << endl; // output: 12
This would not be possible if fun() returned the value of x (the integer 10) instead of a reference to variable x itself (whose value we can update).
int &z = fun() lets us refer to that same static variable through the name z in the same way:
int &z = fun();
cout << z++ << endl;
cout << z++ << endl; // output: 11
cout << z++ << endl; // output: 12
cout << fun() << endl; // output: 13
Both the function return type and z have to be references for the above to work.
If z were not a reference but an int z variable, we would be making a copy of the original value and incrementing that in place of the static variable x itself.
If the function return type were a value (instead of a reference), it would return the value of x, not a reference to x itself. In this case, int f(); int &z = f(); would try to take a reference to the temporary return value of the function. In fact, this code doesn't even compile.
Functions that return static variables (by reference or otherwise) have their uses. One of which is that a static variable inside a function is initialized at runtime, the first time we run through its declaration.
In the code below, init_x() is called when initializing the static variable x. This happens the first time fun() is called to retrieve the value of x.
int& fun() {
static int x = init_x();
return x;
}
int main() {
do_other_stuff();
fun()++; // init_x() is called here
fun()++;
fun()++;
}
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.
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.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
This code takes value returned from a function, creates and puts it in a new address space called variable 'b'
int main()
{
int b;
b = topkek();
std::cout << &b;
};
int topkek()
{
int kek = 2;
return kek;
};
Now I understand because variable kek was inside of topkek method I can not access it from main() method. With C++ and pointers, I figured out how I could access a variable declared inside a method even after the method has terminated, look at this code.
int main()
{
int * a;
a = topkek(); //a is now pointing at kek
std::cout << *a; //outputs 2, the value of kek.
*a = 3;
std::cout << *a; //output 3, changed the value of kek.
std::cin >> *a;
};
int * topkek()
{
int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Is this method safe? Would the compiler prevent kek's address space being overwritten later in code because it still understand it's being used?
This is undefined behavior: once the function finishes, accessing a variable inside it by pointer or reference makes the program invalid, and may cause a crash.
It is perfectly valid, however, to access a variable when you go "back" on the stack:
void assign(int* ptr) {
*ptr = 1234;
}
int main() {
int kek = 5;
cout << kek << endl;
assign(&kek);
cout << kek << endl;
}
Note how assign has accessed the value of a local variable declared inside another function. This is legal, because main has not finished at the time the access has happened.
No it is not safe. After your function finished execution, you are not pointing to an int anymore but just to some random place in memory. Its value could be anything since it can be modified elsewhere in your program.
Most definitely not safe. Undefined behavior will result.
When a local variable is "created", the compiler does so by giving the variable some space on the the stack [1]. This space is available for the variable as long as you are inside that function. When the function returns, the space is released, and available for other functions to use. So the address of b in your second code is returning a pointer to memory that will be releasted just after the return finishes.
Try adding something like this:
int foo()
{
int x = 42;
cout << "x = " << x << endl;
return x;
}
and call foo after your call to topkek, and it's pretty certain that the value in kek (or pointed to by kek) will change.
[1] For the pedants: Yes, the C++ standard doesn't specify that there needs to be a stack, or how local variables are supposed to be used, etc, etc. But in general, in nearly all compilers available today, this is how it works.
This will be safe:
int * topkek()
{
static int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Locally allocated automatic types will be automatically deallocated when exiting the function scope. The pointer you return will then point to deallocated memory. Accessing this memory will result in undefined behaviour.
int* topkek() {
int kek = 2; // Create a local int kek
int* b = &kek; // Declare pointer to kek
return b; // Return pointer to local variable. <-- Never do this!
}; // kek is destroyed and the returned pointer points to deallocated memory.
This is undefined behavior. After returning from the function, kek does not exist any more, and the pointer returned points into nirvana, to the location where kek once was. Accessing it gives undefined behavior. Undefined behavior means, anything can happen. You could indeed get the value that once was in kek or your application crashes, or you get some garbage value, or your compiler sees fit to order you a pizza online, with extra cheese, please.
This is undefined behavior, kek is a local variable and the memory it resides in will be released once you exit topkek. It may seem like it works but since it is undefined anything can result, it can break at any time and you can not rely on the results.
First, this is definitely unsafe as others have noted. But based on your usage, I think you might actually be trying to define an object. For example, this code might be what you want:
struct topkek{
int kek;
int *operator()() {
kek = 2;
return &kek;
}
};
int main()
{
topkek mykek;
int *a = mykek(); // sets mykek.kek to 2, returns pointer to kek
std::cout << *a;
*a = 3;
std::cout << *a;
std::cin >> *a;
};
This will give you clean access to the underlying kek variable in a totally safe way. You can of course put any code you want into the operator() method.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Returning the address of local or temporary variable
Can a local variable's memory be accessed outside its scope?
I know that I should not return pointers to local function variables (local stack variables) because when the function return, the variables will be invalid and the stack will be cleaned up unless I made these variables static or allocated them on heap.
The following code demonstrates that:
const char* v1() {
return "ABC";
}
const char* v2() {
string s = "DEF";
return s.c_str();
}
const char* v3() {
static string s = "JHI";
return s.c_str();
}
cout << v1() << endl; // Output: ABC
cout << v2() << endl; // Output: garbage (♀ ╠╠╠╠╠╠╠╠)
cout << v3() << endl; // Output: JHI
However, I returned pointer to a primitive local function variable and I was able to get its value although it is not static, as the following code shows:
int i1() {
int i = 5;
return i;
}
int* i2() {
int i = 6;
return &i;
}
int* i3() {
static int i = 7;
return &i;
}
cout << i1() << endl; // Output: 5
cout << *i2() << endl; // Output: 6 !!
cout << *i3() << endl; // Output: 7
The compiler only gives me warning that I am returning address of local variable or temporary (Visual C++ 2008). Is this behaviour common to all compilers and how the compiler allows me to use pointer to a local function variable to access the value it points to although the variable is invalidated when the function return?
you return an address. Returning an address is valid - always. But in your case, you also dereference it. This is undefined behavior. Theoretically, for undefined behavior, anything can happen. The compiler is even allowed to embed code to format your hard-disc. Practically it will dereference the address without any checks. If it is still accessible, it'll return the value at that address otherwise it'll cause an access violation.
Your address is on the stack, so it is always accessible. Depending on the calls you made in between, the value might still be there or not. So in simple cases, you get the value back, in more complicated cases you won't. It may even work sometimes and sometimes it does not.
For more information, you should read some information on how function calls are made in assembler to understand what the compiler is doing there on the stack (placing parameters, return address, placing local variables, stack cleanup on return, calling conventions).
it can be removed from the stack because it is local but the value will remain until another overwirte it.
it is c++ unsafe language u can do much strange things