Given the following code:
void Allocate(int *p)
{
p = new int;
*p++ = 2;
}
int main()
{
int i = 10;
Allocate(&i);
std::cout << i << std::endl;
}
I'm a bit confised about the meaning of:
*p++ = 2;
The output is 10 and my reasoning as to why this is the case is that *p++ is a temporary therefore any assignment to it is lost at the end of the scope of Allocate(int *p).
Is this the case?
Thanks in adv!
On input to Allocate, p points to the variable i in the main
function.
The address of this variable then lost and replaced by the
new int.
The value of this int (which is uninitialized and so could
start as anything) is set to 2.
The p pointer is incremented.
The Allocate function returns at this point, leaking the int that was
allocated.
The value of i in the main function is unchanged,
because Allocate did not modify it.
when you pass the the address of i into Allocate, another (temp) pointer is created that points to i's address (i.e. passing by pointer). then that temp pointer is pointed to a new location (via new int). thus the value of i is left alone.
p = new int;
You're assigning p new memory to point to instead of what it was pointing to before. You then change this newly allocated memory and it's lost forever when the function ends, causing a memory leak. If you remove the allocation line, it should cause an output of 2. The ++ does nothing in this case. It just increments the pointer and returns the old value to dereference.
As soon as you enter Allocate, you assign p to point to a new block of memory, so it no longer points to i. Then you modify that new block of memory (which is then leaked when the method returns.) i is unaffected because you've moved that pointer before you set the pointed-to memory cell.
void Allocate(int **p)
{
*p = new int;
**p = 2;
}
int main()
{
int j = 10;
int *i = &j;
std::cout << i << std::endl;
Allocate(&i);
std::cout << i << std::endl;
}
Output is :
10
2
You need a pointer to pointer to change the address of the location being pointed to.
Related
I just learned pointer and delete pointer in class for C++. I tried this code by my own
# include<iostream>
using namespace std;
int main(){
int num = 10;
int *p = new int;
p = #
cout << *p << endl;
delete p;
cout << num << endl;
return 0;
}
After deleting the pointer p, I cannot print the value of num. But if I delete p at the very end of the program, cout << num << endl; will give me 10. Anyone knows where I did run?
You first leaked a pointer
int *p = new int;
p = # // You just leaked the above int
then illegally deleted something you did not new
delete p; // p points to num, which you did not new
You have already received a couple of good answers that point out the mistake, but I read a deeper misunderstanding of the allocation and deallocation of heap vs stack variables.
I realised this has become a pretty long post, so maybe if people think it is useful I should put it as a community Wiki somewhere. Hopefully it clarifies some of your confusion though.
Stack
The stack is a limited and fixed size storage. Local variables will be created here if you don't specify otherwise, and they will be automatically cleaned up when they are no longer needed. That means you don't have to explicitly allocate them - they will start existing the moment you declare them. Also you don't have to deallocate them - they will die when they fall out of scope, loosely speaking: when you reach the end brace of the block they are defined in.
int main() {
int a; // variable a is born here
a = 3;
a++;
} // a goes out of scope and is destroyed here
Pointers
A pointer is just a variable, but instead of an int which holds a whole number or a bool which holds a true/false value or a double which holds a floating point, a pointer holds a memory address. You can request the address of a stack variable using the address operator &:
{
int a = 3, b = 4;
int* p = &a; // p's value is the address of b, e.g. 0x89f2ec42
p = &b; // p now holds the address of b, e.g. 0x137f3ed0.
p++; // p now points one address space further, e.g. 0x137f3ed4
cout << p; // Prints 0x137f3ed4
} // Variables a, b and p go out of scope and die
Note that you should not assume that a and b are "next to" each other in memory, or that if p has a "used" address as its value then you can also read and write to the address at p + 1.
As you probably know, you can access the value at the address by using the pointer indirection operator, e.g.
int* p = &a; // Assume similar as above
*p = 8;
cout << a; // prints 8
cout << &a << p; // prints the address of a twice.
Note that even though I am using a pointer to point at another variable, I don't need to clean up anything: p is just another name for a, in a sense, and since both p and what it points to are cleaned up automatically there is nothing for me to do here.
Heap
The heap memory is a different kind of memory, which is in theory unlimited in size. You can create variables here, but you need to tell C++ explicitly that you want to do so. The way to do this is by calling the new operator, e.g. new int will create an integer on the heap and return the address. The only way you can do something sensible with the allocated memory, is save the address this gives you. The way you do this, is store it in a pointer:
int* heapPtr = new int;
and now you can use the pointer to access the memory:
*heapPtr = 3;
cout << heapPtr; // Will print the address of the allocated integer
cout << *heapPtr; // Will print the value at the address, i.e. 3
The thing is that variables created on the heap will keep on living, until you say you don't need them anymore. You do that by calling delete on the address you want to delete. E.g. if new gave you 0x12345678 that memory will be yours until you call delete 0x12345678. So before you exit your scope, you need to call
delete heapPtr;
and you will tell your system that the address 0x12345678 is available again for the next code that comes along and needs space on the heap.
Leaking memory
Now there is a danger here, and that is, that you may lose the handle. For example, consider the following:
void f() {
int* p = new int;
}
int main() {
f();
cout << "Uh oh...";
}
The function f creates a new integer on the heap. However, the pointer p in which you store the address is a local variable which is destroyed as soon as f exits. Once you are back in the main function, you suddenly have no idea anymore where the integer you allocated was living, so you have no way to call delete on it anymore. This means that - at least for the duration of your program - you will have memory that according to your operating system is occupied, so you cannot use it for anything else. If you do this too often, you may run out of memory even though you can't access any of it.
This is one of the errors you are making:
int* p = new int;
allocates a new integer on the heap and stores the address in p, but in the next line
p = #
you overwrite that with another address. At this point you lose track of the integer on the heap and you have created a memory leak.
Freeing memory
Aside from freeing memory not often enough (i.e. not instead of once), the other error you can make is freeing it too often. Or, to be more precise, you can make the error of accessing memory after you have told your OS you don't need it anymore. For example, consider the following:
int main() {
int* p = new int;
*p = 10;
delete p; // OK!
*p = 3; // Errr...
}
That last line is very wrong! You have just returned the memory allocated when you called delete, but the address is still stored in p. After you call delete, your OS is allowed to re-allocate the memory at any time - for example, immediately after another thread could call new double and get the same address. At that point, if you write *p = 3 you are therefore writing to memory that is no longer yours which may lead to disaster, if you happen to overwrite the location in memory where the nuke's launch codes are stored, or nothing may happen at all because the memory is never used for anything else before your program ends.
Always release your own memory, and nothing but your own memory
We have concluded the following: memory allocated on the stack is not yours to claim, and not yours to release. Memory allocated on the heap is yours to claim, but you must also release it once and only once.
The following examples are incorrect:
{
int a = 3;
int* p = &a;
delete a;
} // Uh oh... cannot clean up a because it is not ours anymore!
{
int* p = new int;
delete p;
*p = 3; // Uh oh, cannot touch this memory anymore!
delete p; // Uh oh, cannot touch this memory anymore!
}
Why does it print 10?
Well, to be honest, you were just "lucky" there. Actually, the way your operating system manages memory, is generally pretty lazy. When you tell it "I would like some memory" it doesn't zero it for you. That is why it is a bad idea to write
int main() {
int a;
a = a + 3;
cout << a;
}
You get allocated a variable a somewhere in the memory, but the value of a will be whatever was in that memory location. It might be zero, or some random number that depends on how the bits fell when you booted your computer. That is why you should always initialize the variable:
int a = 0;
Similarly, when you say "I don't need this memory" anymore, the OS doesn't zero it. That would be slow and unnecessary: all it needs to do is mark the memory as "free to be re-allocated". So if you give it back and access it immediately afterwards, the probability that it has not been re-allocated yet is pretty large. Therefore
int* p = new int;
*p = 10;
delete p;
cout << *p;
is not guaranteed to print 10. The address p is pointing to may have been (partially) taken (and initialized!) by someone else immediately after the delete. But if it hasn't, the memory will still contain the value 10 there so even though it isn't yours anymore, C++ will still allow you to access it. Basically, when you are using pointers, you are telling it "trust me, I'm a programmer - you don't need to do all kinds of slow checks to make sure I'm staying where I'm supposed to be, instead I'll be careful about that myself!"
using namespace std;
int main(){
int num = 10; // a) an int is created on stack
int *p = new int; // b) another int is allocated on heap
p = # // c) address of int from stack is assigned to p and the pointer
// allocated in b) is leaked: as nothing points to it anymore,
// it can't be deleted
cout << *p << endl;
delete p; // d) deleting a pointer that was not dynamically allocated
// and is pointing to stack.
cout << num << endl;
return 0;
}
I have gotten stuck on modifying pointers of pointers. The problem is that I don't understand why my code works. What I am trying to do is modify where a pointer-to-pointer points to in a function. Then accessing that value in my main function. I tried quite a few attempts and this is the only way I got it to work.
#include <iostream>
using namespace std;
void changePP(int **ppint) {
int *n = new int;
*n = 9; //just a value for demonstration purposes
*ppint = n; //THE LINE IN QUESTION
delete n;
}
int main() {
int **ppint = NULL;
int *p = new int;
*p = 4; //another value for demonstrating
ppint = &p;
cout << **ppint << endl;
changePP(ppint);
cout << **ppint << endl;
}
So, the output is 4 and then a 9 on seperate lines. However, I am not sure about the line *ppint = n in the code. Why do I have to use the * to change where ppint points to in the changePP function but not in the main? Also why do I not have to use the & in the function? I can't seem to find an explanation that I can understand on the internet and I was wondering if someone could explain this for me?
Note: these memory addresses are only for illustration.
Memory Layout
0x0A | 4
0x0B | 'p' -> 0x0A // Pointer to the value 4 in location 0x0A
0x0C | 'ppint' -> NULL // Initially a null pointer
Performing ppint = &p; produces the following because here ppint is the pointer located at 0x0C.
0x0A | 4
0x0B | 'p' -> 0x0A
0x0C | 'ppint' -> 0x0B
As for the parameter in the changePP function, I will refer to it as ppintCopy for less confusion. It's a copy (i.e., a pointer different than ppint) and modifying it only modifies the copy.
0x0D | 'ppintCopy' -> 0x0C // A pointer that points to `ppint`
Performing ppintCopy = &n would modify the pointer at 0x0D which is not the location of the pointer from the main function. However, deferencing ppintCopy (i.e., *ppintCopy) yields 0X0C which is the pointer from the main function therefore *ppintCopy = n; is changing where the pointer 0x0C points.
Why do I have to use the * to change where ppint points to in the changePP function but not in the main?
With the above illustration I hope it is more clear why it works in main and why you have to use a different syntax in the changePP function.
Also why do I not have to use the & in the function?
In the main function the variable ppint is of type int** (i.e., a pointer to a pointer) and p is of type int*. You cannot perform ppint = p; because the they are different types. This may be easier to see if you remove one level of indirection. For example:
int* pMyInt = NULL;
int myInt = 3;
I think it's pretty self explanatory that this cannot work (i.e., they are different types).
pMyInt = myInt;
However you can take the address of myInt using the & operator which results in a pointer to int (i.e., int*) and since this type is the same as the type of pMyInt the assignment is now possible.
pMyInt = &myInt;
ppint; // the variable name
*ppint; // dereference the first layer of pointer
*(*ppint); // dereference the first layer of pointer which points to another pointer that contains a **value**
Thus *ppint = n; means point ppint to another memory location which is the location assigned to n or it could be rewritten as *ppint = &n;
After that line, you have deleted the n but you didn't change its value so the value remains unchanged unless something have accessed and modified it.
The reason why you still retain the value of n after deleting it is considered as undefined behaviour though.
Pointers are already messy to deal with, you didn't have to make it worse. This works as well:
#include <iostream>
using namespace std;
void changePP(int *ppint) {
*ppint = 9;
}
int main() {
int p = 4;
int *ppint = &p;
cout << *ppint << endl; // this could be replaced with /*p*/
changePP(ppint); // note you could have replaced this parameter with /*&p*/
cout << *ppint << endl; // this could be replaced with /*p*/
}
Let me try to explain what your code is doing, but please for future, don't ever do it this way. Do it the way I've shown
#include <iostream>
using namespace std;
void changePP(int **ppint) {
int *n = new int; // you allocate memory for a single integer (again it is uninitialised)
*n = 9; // the value at the above pointer is now changed to 9
*ppint = n; // here you have just dereferenced a pointer to pointer which gives you a pointer, so in essence you are changing the location in memory where this pointer is pointing and it is now pointing to whatever memory address n was
delete n;
}
int main() {
int **ppint = NULL; // Here you have declared a pointer to pointer which is NULL
int *p = new int; // You can do better here with /*new int(4)*/
*p = 4; // this changes the value that p initially held (which could be anything)
ppint = &p; // reference to a pointer always creates a pointer to a pointer and since that is what ppint is, you are safe here
cout << **ppint << endl; // print the value nested within this pointer
changePP(ppint); // now you call the function with a variable of type pointer to pointer. Note you could have passed &p as parameter here and it would have still worked
cout << **ppint << endl;
}
What is the moral of the story?
When passing a parameter v to a function,
&v will produce a pointer to v
*v will dereference v and will give you access to whatever v was pointing to
When v is a parameter in a function,
&v will bring the actual object v into the scope of the function. This is called pass by reference
*v Is a pointer to v, and this is still pass by reference called pass by value because you are passing a pointer(Thanks Kirk)
A very general question: I was wondering why we use pointer to pointer?
A pointer to pointer will hold the address of a pointer which in turn will point to another pointer. But, this could be achieved even by using a single pointer.
Consider the following example:
{
int number = 10;
int *a = NULL;
a = &number;
int *b = a;
int *pointer1 = NULL;
pointer1 = b; //pointer1 points to the address of number which has value 10
int **pointer2 = NULL;
pointer2 = &b; //pointer2 points to the address of b which in turn points to the address of number which has value 10. Why **pointer2??
return 0;
}
I think you answered your own question, the code is correct, what you commented isn't.
int number = 10; is the value
int *pointer1 = b; points to the address where int number is kept
int **pointer2 = &b; points to the address where address of int number is kept
Do you see the pattern here??
address = * (single indirection)
address of address = ** (double indirection)
The following expressions are true:
*pointer2 == b
**pointer2 == 10
The following is not!
*pointer2 == 10
Pointer to pointer can be useful when you want to change to what a pointer points to outside of a function. For example
void func(int** ptr)
{
*ptr = new int;
**ptr = 1337;
}
int main()
{
int* p = NULL;
func(&p);
std::cout << *p << std::endl; // writes 1337 to console
delete p;
}
A stupid example to show what can be achieved :) With just a pointer this can not be done.
First of all, a pointer doesn't point to a value. It point to a memory location (that is it contains a memory address) which in turn contains a value. So when you write
pointer1 = b;
pointer1 points to the same memory location as b which is the variable number. Now after that is you execute
pointer2 = &b;
Then pointer2 point to the memory location of b which doesn't contains 10 but the address of the variable number
Your assumption is incorrect. pointer2 does not point to the value 10, but to the (address of the) pointer b. Dereferencing pointer2 with the * operator produces an int *, not an int.
You need pointers to pointers for the same reasons you need pointers in the first place: to implement pass-by-reference parameters in function calls, to effect sharing of data between data structures, and so on.
In c such construction made sense, with bigger data structures. The OOP in C, because of lack of possibility to implement methods withing structures, the methods had c++ this parameter passed explicitly. Also some structures were defined by a pointer to one specially selected element, which was held in the scope global to the methods.
So when you wanted to pass whole stucture, E.g. a tree, and needed to change the root, or 1st element of a list, you passes a pointer-to-a-pointer to this special root/head element, so you could change it.
Note: This is c-style implementation using c++ syntax for convienience.
void add_element_to_list(List** list, Data element){
Data new_el = new Data(element); // this would be malloc and struct copy
*list = new_el; //move the address of list, so it begins at new element
}
In c++ there is reference mechanismm and you generally you can implement nearly anything with it. It basically makes usage of pointers at all obsolete it c++, at least in many, many cases. You also design objects and work on them, and everything is hidden under the hood those two.
There was also a nice question lately "Why do we use pointers in c++?" or something like that.
A simple example is an implementation of a matrix (it's an example, it's not the best way to implement matrices in C++).
int nrows = 10;
int ncols = 15;
double** M = new double*[nrows];
for(unsigned long int i = 0; i < nrows; ++i)
M[i] = new double[ncols];
M[3][7] = 3.1416;
You'll rarely see this construct in normal C++ code, since C++ has references. It's useful in C for "passing by reference:"
int allocate_something(void **p)
{
*p = malloc(whatever);
if (*p)
return 1;
else
return 0;
}
The equivalent C++ code would use void *&p for the parameter.
Still, you could imagine e.g. a resource monitor like this:
struct Resource;
struct Holder
{
Resource *res;
};
struct Monitor
{
Resource **res;
void monitor(const Holder &h) { res = &h.res; }
Resource& getResource() const { return **res; }
}
Yes, it's contrived, but the idea's there - it will keep a pointer to the pointer stored in a holder, and correctly return that resource even when the holder's res pointer changes.
Of course, it's a dangling dereference waiting to happen - normally, you'd avoid code like this.
I was reading through MIT's Introduction to C++ and one code example showed:
int *getPtrToFive() {
int *x = new int;
*x = 5;
return x;
}
int main() {
int *p;
for (int i = 0; i < 3; ++i) {
p = getPtrToFive();
cout << *p << endl;
delete p;
}
}
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new".
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
I was wondering why it is possible to delete "p" after every iteration despite "p" being declared once before the loop started and was not allocated using "new"
No. You are not deleting p, you are deleting the object p points to, which is allocated using new each iteration.
Another question is when "*x" is assigned the value 5 in the function, since it is a pointer the memory address would be changed right? So it would be something like 0x00005 instead of the actual value 5?
The value of x would be something like 0xFFd00whatever. but you are printing the value of *x, which is "the number that is in the memory at address 0xFFd00whatever". There is no x=5 in your code; there's only *x=5. It means "go to the address to which x points to, and put the number 5 in there".
You can think about it this way: you have a hand, okay? let's call it "x". The command
x = new int;
Means "point your finger at some empty place on your desk." Where
*x = 5;
Means "draw the number five where your hand points to".
p is simply a variable of the type int* (pointer to int). Its value is an address. When you assign a new value to it then it points to a new object. delete expects an address; that's all it needs to deallocate the memory you allocated.
The variable used to store said address is irrelevant. It's value has changed, and that's all delete cares about; the value.
Newb question here:
how can I have the value stored in Maptest[2] update along with the variable?
I thought you could do it with pointers, but this doesn't work:
map<int, int*> MapTest; //create a map
int x = 7;
//this part gives an error:
//"Indirection requires pointer operand ("int" invalid)"
MapTest[2] = *x;
cout << MapTest[2]<<endl; //should print out 7...
x = 10;
cout <<MapTest[2]<<endl; //should print out 10...
What am I doing wrong?
You need the address of x. Your current code is attempting to dereference an integer.
MapTest[2] = &x;
You then need to dereference what MapTest[2] returns.
cout << *MapTest[2]<<endl;
Try this instead:
MapTest[2] = &x;
You want the address of x to store in the int*. Not the dereference of x, which would be what ever is at the memory location 0x7, which is not going to be valid.
There are at least 2 problems here:
int x = 7;
*x; // dereferences a pointer and x is not a pointer.
m[2] = x; // tries to assign an int value to a pointer-to-int value
// right
m[2] = &x; // & returns the address of a value
Now you have a new problem. x has automatic lifetime, it will be
destroyed at the end of its surrounding scope. You need to allocate it
from the free store (a.k.a. the heap).
int* x = new int(7);
m[2] = x; // works assigns pointer-to-int value to a pointer-to-int value
Now you have to remember to delete every element in the map before
it goes out of scope or you will leak memory.
It is smarter to store values in a map, or if you really need to
store pointers to store a suitable smart pointer (shared_ptr or
unique_ptr).
For the printing:
m[2]; // returns pointer value
*m[2]; // dereferences said pointer value and gives you the value that is being pointed to