Sunday, December 14, 2008

Week 2, Day 1

All about the Pointers.

Today's "Class"
Today featured a lengthy introduction to pointers and an explanation of how they actually function. Apparently pointers are one of the more difficult concepts to grasp for new C++ programmers. I can imagine. It isn't that the concept is confusing in theory, it is the practice that is a bit bothersome for me. To a degree, I understand WHY pointers are valuable. Being able to store variables on the "free store" of the RAM, safely tucked awa... int * pMyVariable = 0...y for use by any functions, is like creating SUPER GLOBAL variables. And yet you still get to control how much access is given to these variables by carefully using objects and the const keywoard to protect writing to the variable (and / or the pointer).
What is difficult to grasp is exactly WHY you would need to use pointers. The book says by the end of the "week" the reader will have a good grasp of what to use pointers for and whatnot. I guess I'll have to take it on faith then.

pointers - What are they?
pointers hold an address of a variable. Every variable in C++ is stored on the RAM. Well, this should be true of any programming language really. Anyway, so in C++ when you have variables on the RAM you can actually retrieve it's address in a fairly straightforward manner. Example code snippet to see an address of a variable:
...
int myVariable = 5;
cout << "myVariable is located at: " << &myVariable;
...

This little bit of code (when placed in a properly set up program), will print the address of the variable you declared the line above. It will not print 5. Instead it will print a hexidecimal (I think) code of WHERE the value for myVariable is PHYSICALLY stored on your RAM. Run this program a dozen times and you could get a dozen different values. Or they could all be the same, it just depends on your OS and your physical hardware.
So, like I said... a pointer STORES the address of a variable. Which means I have not shown you a pointer yet. You define a pointer in a very similar fashion to defining a variable. Let's redo the code snippet above to actually use a pointer shall we?
...
int myVariable = 5;
int * pMyVariable = &myVariable;
cout << "myVariable is located at: " << pMyVariable;
...

As you can see, it is pretty easy, like anything else in C++ once you understand the concepts. Now, there are three VERY important things to pay attention to when declaring a pointer.
(1) a pointer needs to be defined as the exact same type of variable as what it is pointing at. We were pointing to an int, so the pointer had to be an int as well.
(2) don't forget the asterisk. That is what is letting the compiler know this is a pointer.
(3) either point the pointer to an address of a variable, define a new variable for the pointer, or POINT IT AT NULL (... int * pMyVariable = 0; ...). If you have the pointer "dangling" or "wild" or "stray" it could cause some rather unpleasant bugs in your program that will be a nightmare to find in the future.

What's the Point
To understand why you need to be able to use pointers in the first place, you need to understand the basic structure of how computers store information in the RAM. Go get a book, as that is a topic and a half. You don't need to know the mechanical function of RAM or the technical specs, but you do need to know how the RAM houses information in different "areas" and what happens to each area in C++ while the program functions. I have said it before, and I will say it again... if you want to actually learn C++, go beyond just reading me review what I have learned... buy a book or enroll in a class. The benefits of being taught correctly the first time through is muy bien.

Pointers can access the data too!
So, pointers also can access the data of the variable they point to. It could be slightly confusing I guess, but with practice it doesn't seem to bother me anymore. The example we wrote before... let's change the variable data and see how it works eh?
...
int myVariable = 5;
int * pMyVariable = &myVariable;

cout << "myVariable, located at " << pMyVariable

*pMyVariable = 10;
cout << "myVariable, located at " << pMyVariable
...

Look confusing at all? The asterisk has dual function. When you are defining the pointer, it informs the compiler that this variable contains an address. When you are using it any other time in your code, it says that you are accessing the VALUE stored at the address the pointer points to.
So, in the above example:
pMyVariable would equal some hexidecimal address
*pMyVariable starts out as 5, and then we change it to 10. *pMyVariable is identical to myVariable in this example. When one changes, the other changes as well. They are just different labels for the same data.

Practical Uses of pointers
I don't have a full grasp on what the usages are yet, that will come tomorrow and in the following days, but I can give an overview.
pointers store data on the "free store" part of the RAM, which means after the function is over, the data is still there (unless you explicitely delete it). Of course, you have to make sure you can still ACCESS that data... otherwise you have a memory leak. The data will still reside in the address the pointer points to, BUT the pointer variable itself is stored in the "stack" of the function, so after it is done it will be GONE, unless you have the pointer somewhere other than the function and you are passing it into the function in the first place.
The one example the book gave (and the author didn't have me make this so I am not sure how exactly it works yet), is a word processor. A dialog box needs to have access to the document, but once the dialog box finishes it's task... we don't want the document disappearing. Makes sense... but why not just use an object for the document? I don't know, I'm sure there are reasons.

pointers can also CREATE a variable. The example we listed before, here is yet another version of it:
...
int * pMyVariable = new int (5);
cout << "pMyVariable points to: " << pMyVariable
cout << "*pMyVariable is: " << *pMyVariable << "\n";
...

This should demonstrate what I am talking about. You can of course use pointers for objects as well. It would be the same as before, but instead of type int, you would use your class name. To access functions from the pointer for that object... you would do something like this:
...
fish * pGoldfish = new fish;
cout << "pGoldfish is a fish with the default weight of " << pGoldfish->GetWeight() << " lbs.\n";
pGoldfish->SetWeight(10);
cout << "pGoldfish is now 10 lbs, see: " << pGoldfish->GetWeight() << " lbs.\n";
...

Obviously, you would need to have a class named "fish" with the functions "GetWeight()" and "SetWeight( int weight )". And having a default weight in the constructor would be a very good thing if you are going to copy and paste that little snippet above. The "->" accesses functions of an object through a pointer. Notice that you don't need an asterisk to get into the functions.

Summary and Workshop
That is just about all they covered. The end of the chapter demonstrated a program that seperates a string into words. The program obviously used pointers to do a lot of brunt work and showed how flexible they are when traversing functions. The exercises were very, very easy. Just making sure you understood how to use pointers really.

No comments: