USHORT * pInt = new USHORT;
        *pInt = 10;
       std::cout << "*pInt: " << *pInt << endl;       
       
       long * pLong = new long;
       *pLong = 90000;
       std::cout << "*pLong: " << *pLong << endl;
       *pInt = 20;      
       std::cout << "*pInt: " << *pInt  << endl;
	   delete pInt;

	   *pInt = 30;

       std::cout << "*pLong: " << *pLong  << endl;
	   std::cout << "*pInt: " << *pInt  << endl;
       delete pLong;

I have deleted pInt...why is this not throwing an exception when assign 30 to it?

Im pretty sure the reason that you are not getting an exception is because even though you have called delete the pointer still points to the same address. This definitely is dangerous because you have freed the memory so you cant be sure you are not overwriting something else that was assigned to that address. As a side note most people I have seen using pointer and myself included will set the pointer to NULL after calling delete.

I have deleted pInt

This means "I have told the operating system that I don't care what it does with the memory pInt is pointing to". That's all it means. pInt still exists, pInt still contains the same memory address, and frequently that memory will contain the exact same values, untouched, for a while. Why would this throw an exception?

Edited 5 Years Ago by Moschops: n/a

As NathanOliver stated, it's a good practice to assign 0 (NULL) to the pointer after using delete because after calling delete the memory object pointed to should no longer be used since it has been destructed and no longer belongs to your program.

So let me get this straight.....the area on the stack for pInt is reserved when I compile my program. Once I call delete on pInt it is then telling the OS that it can use the memory that pInt was stored in however it wishes??

FirstPerson....you are right...it doesn't help going from C# to C++....kind of think it would be much easier the other way around!

So let me get this straight.....the area on the stack for pInt is reserved when I compile my program. Once I call delete on pInt it is then telling the OS that it can use the memory that pInt was stored in however it wishes??

No. That's unfortunately wrong. I think you've not understood what a pointer is. The memory the pointer takes up is completely unchanged when you use delete. hang on, let me fetch something.... here, read this and tell me if you don't understand any of it. Once you understand what a pointer is, you can then work on what delete and new do.

----------------------

You are familiar with an int? An int is an object that takes up an amount of memory (commonly 4 bytes, sometimes 8) and stores a single numerical value.

A pointer looks exactly the same as that. It takes up the same amount of memory as an int, and stores a single numerical value. All pointers look the same, whether they are pointers to int or pointers to double or whatever. They take up the same space and store a single numerical value.

With me so far?

Now, you know how to create an int? Like this:

int a;

You create a pointer exactly the same way;

int* a; // This create a pointer to an int
double* b; // This creates a pointer to a double

Like any object, you have to create a pointer before you can use it.

You can create a pointer to any kind of object you can think of using this syntax, but don't be fooled - the pointers all take up 4 (sometimes 8) bytes and store a single numerical value.

You know that if you create an int without assigning it a value, it'll be just some garbage value? Just whatebver happens to be in the memory at the time.

int b; // This int could have any value at all

Same thing with pointers

int* b; // This int pointer could have any value at all

Of course, the same rules for naming things apply, so this:

int a;
int* a;

would refuse to compile, as I have two objects with the same name.

So far, so simple, yes?

There is one special thing a pointer can do. You recall that the pointer stores a single numerical value? I can carry out an operation called "dereferencing" on the pointer, and that simply means I get back whatever object is in the memory location of that single numerical value. So, if I my pointer stores the value 0x22334455 (I've used hex here, but it's just a number), when I dereference the pointer, I get back whatever is at memory location 0x22334455. We sometimes say that the pointer is pointing at the object in memory location 0x22334455.

How do we know what numerical value to put into a pointer (or, put another way, how do we know what the memory address of an object is, so that we can store than memory address in the pointer)? Fortunately, there exists an operator "&" which will return the address of any object (i.e. the numerical value of the place in memory where that object is).

int a; // an integer
&a; // the address of that integer

So here's how we could use that:

int* p; // a new pointer, with some garbage value - could be pointing anywhere
p = &a; // now we've stored the address of a in the pointer, so now the pointer is pointing at the object a

There are circumstances where you might need to manually enter the address location yourself, and you can do that. Say you knew for sure that a value of interest was at address location 0x2323FFFF. You can manually set it, and we'll cover that a bit later.

If all pointers are the same size and store a single numerical value, why do we have int* and double* and string* and all the rest? Because we need to know what kind of object we will get back when we dereference them. That's all. If we were being awkward, we could make an int*, and then force it to point to a double, because the pointer just stores a number - it does not store anything about what kind of thing it's pointing to. That's a bit more advanced, though.

We do this dereferencing operation with the "*". So, if I had a pointer called MrPointer, and I wanted to get what it was pointing at, I would do this:

*MrPointer;

Let's say it points at an int. I could do this:

int someInt = *MrPointer;

or I can just use it in an expression

int anotherInt = 4 + *MrPointer;

Is all this clear? If so, we can explain what new and delete have to do with it.

Edited 5 Years Ago by Moschops: n/a

Wow Moschops thanks for the answer!! It is very clear...sounds like you have a bit more for me?? I am interested in knowing what the delete does! And yes it makes a lot of sense.

Thanks again!

Right, so now we know that a pointer is a complete object in memory, that looks very much like an int (and that seems sensible - all a pointer does is store a number).

Now, when you use the new operator, you get back a pointer (i.e. you get back a number, and that number represents some position in memory). This is because the new operator allocates some memory for us, and then has to tell us where that memory is. How to you store a memory address? In a pointer, of course.

int* somePointer; // Make a pointer to an int. Not given it a value, so
             // it will have some garbage value. It points somewhere random in memory
somePointer = new int; // now it points to some memory somewhere that new found for us, an in that memory
                      // is an int object that new made for us

This makes sense, then. We made a pointer, and then we set the value of that pointer to a value returned by the new operator.

Now we have a pointer that we made, taking up some memory (probably 4 bytes), and then new made an int somewhere else in memory, probably taking up 4 bytes, and our pointer contains the value of the memory address where that int is. So in total, we've now occupied 8 bytes, with two objects.

That memory allocated by new will not be reused until we say it can be. The way we say it can be reused (which effectively means that we're done with that int, and we don't care about it anymore) is by using the delete operator.

delete somePointer;

This indicates to whatever is keeping track of the memory (i.e. the operating system) that we don't care about the object somePointer is pointing at. The operating system will make a note that it can reuse that memory for something else. That's all. Maybe the memory gets reused straight away. Maybe it never gets touched again. There's no way to know, so don't try to read that int again! It might not be there. (Note also that the default destructor will be run - depending on what the object is and how you wrote the destructor, that may or may not change the objects values)

What about the pointer somePointer? That still exists. delete somePointer; does not do anything to the pointer - it just affects the memory at the numerical memory location the pointer is storing.

What if somePointer has changed, and now points somewhere else? Disaster. The operating system does not keep track of the memory for us, so if we have changed the value of the pointer (which I remind you means the pointer contains a different number, which means a different memory address), and then we tell the operating system that we don't care about whatever memory it's pointing to, we could be pointing at memory that wasn't allocated by new! Disaster! We musn't do this:

int* somePointer = new int; // somePointer points at memory new gave us
int a;
somePointer = &a; // now somePointer points at the memory that the int a lives in, which was NOT from new
delete somePointer; // Disaster! Can only apply delete to memory that came from new!

What happens in this following case?

{
int* somePointer;
somePointer = new int;
}
// end of scope - somePointer is gone!

At the end of the scope, we cannot access somePointer anymore. It's gone. What about the memory allocated by new? That's still there - we didn't delete it. Do we know what memory address it is? No. We've lost it. We can never find out that memory address, so we can never delete. It will be taken up until the program finishes and the OS takes back all the memory. This is known as a memory leak.

Be aware that in C++, new does more than just allocate some memory - it then runs the object's default constructor. The delete doesn't just tell the OS that the memory is available again- it first runs the default destructor.

Edited 5 Years Ago by Moschops: n/a

This article has been dead for over six months. Start a new discussion instead.