Lets say I have following function, and it has an argument which is type T. What is life time of that argument.
int* f()
{
int x=0;
int* ptr=&x;
return ptr; //i know this is undefined behavior.
}
So in f() function when it s called, local expressios will run and end of scope pointed value will be deleted. But my question is for following function
void f2(int* y)
{
}
int main()
{
int p=0;
f2(&p);
cout<<p<<endl;
return 0;
}
Here, when we call f2() when that parameter int* y will be deleted? And so if its deleted logicaly pointed value will be deleted which is p, why I can see value of p same using cout? So when f2's argument will be deleted? when function's end scope? or what?
In void f2(int* y), you have a copy of a pointer. The lifetime of that pointer object y, extends to the end of the function f2.
In your main function, you have an integer p. The lifetime of p extends to the end of main.
When calling f2(&p), a temporary pointer is created to be passed to f2. It does not modify the lifetime of p. So, when f2 returns, the temporary pointer is no longer in scope, however p is still in scope (and therefore, valid).
All of the variables shown have automatic storage duration and do not require explicit "deletion".
The function does no memory management on arguments you pass it unless the argument is passed by value (technically everything is passed by value in c++, except a reference, but in the case of a pointer there isn't much to clean up). In the case of your code p is destructed when main's scope ends. Remember this is because p has automatic storage if it had dynamic storage it would be deleted only when you call delete on it.
Now in general there is no reason to pass around an automatic variable as a ptr because c++ has this great thing called pass by reference
void f2(int& y)
This is what you should be doing in most cases
A function parameter is just a local variable in the block scope of the function body. The difference between a function parameter and an ordinary block scope variable is that before the body begins executing, the function parameter is initialized from the corresponding function call expression.
The lifetime of the variable y extends only over the execution of the body of function f.
The object which the pointer object named y points to has a lifetime which is completely unrelated to y.
Pointers are not "deleted" automatically (in the sense that the delete operator is applied to them) at end-of-scope. The variable containing the address itself will be deleted, but the data it points to will not.
You might look at std::unique_ptr, which does what you're describing.
p is created on stack when main is entered. you call f and pass the address of p to it. The f's parameter y gets this address. y is also stored on stack. When f returns, y is deleted because it is a local variable, but p still exists and you print its value. Similar to y, the local variable p is deleted when main exits.
Related
Is passing pointer argument, pass by value in C++? Since i see that any change to the pointer as such is not reflected outside the method. The changes i do by dereferencing the pointer is reflected though.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
Yes to both.
Pointers are passed by value as anything else. That means the contents of the pointer variable (the address of the object pointed to) is copied. That means that if you change the value of the pointer in the function body, that change will not be reflected in the external pointer that will still point to the old object. But you can change the value of the object pointed to.
If you want to reflect changes made to the pointer to the external pointer (make it point to something else), you need two levels of indirection (pointer to pointer). When calling functions it's done by putting a & before the name of the pointer. It is the standard C way of doing things.
When using C++, using references is preferred to pointer (henceforth also to pointer to pointer).
For the why references should be preferred to pointers, there is several reasons:
references introduce less syntaxic noise than pointers in function body
references keep more informations than pointers, than can be useful for compiler
Drawbacks of references are mostly:
they break the simple pass-by-value rule of C, what makes understanding the behavior of a function regarding of parameters (will they be changed ?) less obvious. You also need function prototype to be sure. But that is not really worse than the multiple pointer levels necessary when using C.
they are not supported by C, that can be a problem when you write code that should work with both C and C++ programs (but that's not the most usual case).
In the specific case of pointer to pointer, the difference is mostly simplicity, but using reference it may also be easy to remove both levels of pointers and pass only one reference instead of a pointer to pointer.
I understand the confusion here. The concepts of "pass by value" and "pass by reference" are not so clear even if they seem to be so.
Bear in mind that the computer does not know these concepts and does not behave according to it.
The computer does not know about the types. Hence it does not make a distinction of pointers and values.
Let me try to explain by and example:
void func1(int x) //copy some value to local variable x (of type int)
{
x = 5; //modify local variable. lost after function call
}
void func2(int *x) //copy some value to local variable x (of type int*)
{
int a;
x = &a; //modify local variable. lost after function call.
}
void func3(int *x) //copy some value to local variable x(of type int*)
{
*x = 10; //x is local but *x is not! change is saved after function call!
}
func1 and func2 are identical. Both modify a local variable. Modification is lost after function is popped off the stack.
func3 has ability to change another memory location (a variable which is not local to the function).
basically, every function call is "call by value". But in the case of a pointer type, we have a way to change the content of a remote address in memory.
Pass by value using Pointers
I'll explain it by example:
void f(int *ptr)
{
cout<<*ptr;
}
int main ()
{
int a=10;
int *aptr=&a;
f(aptr);
return 0;
}
Here, in main function a is an integer variable whose content is 10 and address is 00F8FB04 (assume).
aptr is pointer to integer, that store the address of integer variable a, so aptr content is address of integer variable a that is 00F8FB04. When we pass aptr as the function argument only content of aptr (that is address) are copies to function parameter.
So, ptr will receive the copy of content of aptr (that is address 00F8FB04)
Either a pointer to a pointer, or a reference to a pointer, is what you would use if you wanted to potentially change the pointer itself. To your original question, technically, yes, all parameters are passed by value.
Yes it is, as it is in C.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
In which case? What do you want? You can use real references with the & modifier.
void func(type &ref);
struct SGetWindow
{
HWND__* pWindow;
};
SGetWindow getWindow;
EnumWindows(GetWindowProc, reinterpret_cast<LParam>(&getWindow));
return getWindow.pWindow;
Using SGetWindow struct as LParam, HWND__* pWindow is successfully updated.
I wonder if this usage of returning member variable of local struct variable is safe.
return getwindow.pWindow;
Is it safe? or cause undefined behavior?
EDIT: I added an image for understanding.
I understood that the value of pointer (0x00000000000506D8 or 0x00000000000606D8) 1) is valid after function termination, 2) will be copied. But I don't think that guarantees safeness because the matter it seems is 'access (local struct member variable that no longer exist), and return its value'.
EDIT2:
I was thinking wrong and I was so dumb.
According to what I was thinking, even returning local int variable would lead to undefined behavior. For example,
int func()
{
int a = 10;
return a;
}
Local variable 'a' no longer valid when function exits. Thus, return value is undefined behavior.
However, this isn't. Because it is 'return by value' type. The value is copied (somewhere), and the copy process is before local variable goes out of scope.
Operation sequence would be something like
Allocate n bytes for local variable and set its value as 10.
2. Copy the local variable's value to 'somewhere'.
Function exits and local variables become invalid (reverting EBP).
"Another advantage of return by value is that you can return variables (or expressions) that involve local variables declared within the function without having to worry about scoping issues. Because the variables are evaluated before the function returns, and a copy of the value is returned to the caller, there are no problems when the function’s variable goes out of scope at the end of the function."
https://www.learncpp.com/cpp-tutorial/74a-returning-values-by-value-reference-and-address/
"The copy-initialization of the result of the function call is sequenced-before the destruction of all temporaries at the end of expression, which, in turn, is sequenced-before the destruction of local variables of the block enclosing the return statement."
https://en.cppreference.com/w/cpp/language/return
EBP revert
https://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames
Shame on me!
Thank you for kind answers by the way.
This is safe.
You're returning the value of getWindow.pWindow, which happens to be a pointer. This pointer was populated by a call to EnumWindows, not by assigning the address of a local variable.
It's fine, assuming the address in pWindow will continue to exist after the function returns. You can't return a pointer to pWindow (&getWindow.pWindow), but you can return its value (getWindow.pWindow), as long as the value remains valid. pWindow is destroyed when the function returns but that's okay since its value is being copied. If pWindow points to a local variable then you can't do it, but if it points elsewhere then it's safe.
Is there any difference between these two pieces of code?
CPoint temp(x,y);
some_func(temp);
and
some_func(CPoint(x,y));
The lifetime of the CPoint objects is different.
In the first case, a variable named 'temp' is created. It will not be destroyed until after the scope within which it is declared is exited.
In the second case, a true temporary value is created and passed to the function, which will be destroyed as soon as some_func has returned.
Yes, in the first case, the temp var will not be destroyed until the end of the scope. In the second case it will be.
If your function some_func() takes a non const reference as a parameter, the second will not compile since you can not have a reference to something which will be destroyed right away (when some_func returns).
In the first case, if your some_func() function takes a reference, you should be aware that the temp variable will only exist until the current scope ends.
What happens to the reference in function parameter, if it gets destroyed when the function returns, then how const int *i is still a valid pointer?
const int* func(const int &x = 5)
{
return &x;
}
int main()
{
const int *i = func();
}
§12.2/5:
"A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call."
That means as i is being initialized, it's getting the address of a temporary object that does exist at that point. As soon as i is initialized, however, the temporary object will be destroyed, and i will become just another dangling pointer.
As such, yes, the function is valid -- but with the surrounding code as you've written it, any code you added afterward that attempted to dereference i would give undefined behavior.
Just because a pointer has a value doesn't mean it's a valid pointer.
In this case it holds an address which used to be that of x, and chances are that address still has the value 5, but it's not valid pointer and you can't count on that value being there.
int i points to a patch of memory that is unsafe to access, it is not a valid pointer.
the variable "i" is still a pointer, but even reading the value it points to will give you undefined behavior. That's why you should never write a function like func.
I think that x is created as an un-named temporary on the stack in setting up the call to func(). This temporary will exist until at least the end of the statement in the caller. So the int* i is perfectly valid. It only ceases to be valid at the end of the statement - which means that you cannot use it.
There is something in the standard about un-named temporaries being retained until the last reference to them goes out of scope, but I don't think it covers this explicit and hidden indirection.
[ Happy to have someone tell me otherwise.]
5 is program data. It is in the data segment, not the stack or heap.
So a pointer or reference to it will remain valid for the duration of the program.
Default arguments are evaluated every time the function is called, so the call func() is actually func(5) which is binding a temporary to a reference-to-const. The lifetime of that temporary is then extended till the end of the function and the object is destroyed. Any pointer to this object after that is invalid and dereferencing it is undefined behaviour.
Is passing pointer argument, pass by value in C++? Since i see that any change to the pointer as such is not reflected outside the method. The changes i do by dereferencing the pointer is reflected though.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
Yes to both.
Pointers are passed by value as anything else. That means the contents of the pointer variable (the address of the object pointed to) is copied. That means that if you change the value of the pointer in the function body, that change will not be reflected in the external pointer that will still point to the old object. But you can change the value of the object pointed to.
If you want to reflect changes made to the pointer to the external pointer (make it point to something else), you need two levels of indirection (pointer to pointer). When calling functions it's done by putting a & before the name of the pointer. It is the standard C way of doing things.
When using C++, using references is preferred to pointer (henceforth also to pointer to pointer).
For the why references should be preferred to pointers, there is several reasons:
references introduce less syntaxic noise than pointers in function body
references keep more informations than pointers, than can be useful for compiler
Drawbacks of references are mostly:
they break the simple pass-by-value rule of C, what makes understanding the behavior of a function regarding of parameters (will they be changed ?) less obvious. You also need function prototype to be sure. But that is not really worse than the multiple pointer levels necessary when using C.
they are not supported by C, that can be a problem when you write code that should work with both C and C++ programs (but that's not the most usual case).
In the specific case of pointer to pointer, the difference is mostly simplicity, but using reference it may also be easy to remove both levels of pointers and pass only one reference instead of a pointer to pointer.
I understand the confusion here. The concepts of "pass by value" and "pass by reference" are not so clear even if they seem to be so.
Bear in mind that the computer does not know these concepts and does not behave according to it.
The computer does not know about the types. Hence it does not make a distinction of pointers and values.
Let me try to explain by and example:
void func1(int x) //copy some value to local variable x (of type int)
{
x = 5; //modify local variable. lost after function call
}
void func2(int *x) //copy some value to local variable x (of type int*)
{
int a;
x = &a; //modify local variable. lost after function call.
}
void func3(int *x) //copy some value to local variable x(of type int*)
{
*x = 10; //x is local but *x is not! change is saved after function call!
}
func1 and func2 are identical. Both modify a local variable. Modification is lost after function is popped off the stack.
func3 has ability to change another memory location (a variable which is not local to the function).
basically, every function call is "call by value". But in the case of a pointer type, we have a way to change the content of a remote address in memory.
Pass by value using Pointers
I'll explain it by example:
void f(int *ptr)
{
cout<<*ptr;
}
int main ()
{
int a=10;
int *aptr=&a;
f(aptr);
return 0;
}
Here, in main function a is an integer variable whose content is 10 and address is 00F8FB04 (assume).
aptr is pointer to integer, that store the address of integer variable a, so aptr content is address of integer variable a that is 00F8FB04. When we pass aptr as the function argument only content of aptr (that is address) are copies to function parameter.
So, ptr will receive the copy of content of aptr (that is address 00F8FB04)
Either a pointer to a pointer, or a reference to a pointer, is what you would use if you wanted to potentially change the pointer itself. To your original question, technically, yes, all parameters are passed by value.
Yes it is, as it is in C.
In that case, is it acceptable/standard procedure to use pointer to pointer as argument to a function to modify the pointer value as such within a function?
In which case? What do you want? You can use real references with the & modifier.
void func(type &ref);