Reputation: 1411
Consider the following example
class Foo{
public:
Foo(int i):x(i){}
int x;
};
void
bar(Foo *p2)
{
delete p2;
p2 = new Foo(2);
}
int
main()
{
Foo *p1 = new Foo(1);
cout<<p1->x;
bar(p1);
cout<<p1->x;
}
To my understanding, pointer variables are stored on the stack and contains an address to the dynamically allocated memory on the heap which it's "pointing" to. Now, when I pass a pointer to the function a second pointer is created on the stack, pointing to the same memory address as the first pointer. When I delete p2 in bar() and allocate new memory, p1 and p2 should be pointing to different addresses, right?
However, if I compile this code I get 1 and 2 as output. Is this because p2 manage to allocate the same memory cell to which p1 is already pointing to, or is there something I have missed?
Upvotes: 0
Views: 152
Reputation: 162
Except in your sample, pointer variable aren't necessarily on the stack and the address they reference isn't necessarily on the heap, (but new and malloc both return an address on the heap). Both a pointer variable and the address it references can be on the stack, the heap, the global/static variables area or even a ROM. The remaining of your explanation is correct but the behaviour you observe is undetermined and it's really very dangerous to expect it to be reproducible. Any change, a different runtime version, a multi-thread situation, compilation on a different architecture or with another compiler can completely change the result: random value or crash.
Upvotes: 0
Reputation: 168846
Is this because p2 manage to allocate the same memory cell to which p1 is already pointing to, or is there something I have missed?
You missed nothing. You have correctly identified that this program's behavior is undefined. By definition, it could print anything at all, including 2
.
In your run, it is only coincidence (and very likely, the coincidence that you identified) that causes it to print 2
. You might disrupt that chain of coincidence by adding new int(47)
after the delete
and before the existing new
.
If your desire is for the program to behave the way it does, but through defined behaviors, you may make this small change to bar
's definition:
void
bar(Foo*& p2)
This passes the parameter by reference instead of by value. By doing this, changes to the variable p2
inside bar
are reflected in p1
inside `main.
Upvotes: 1