Welcome Guest [Log In] [Register]
We hope you enjoy your visit.


You're currently viewing the Ultimate 3D Community as a guest. This means that you can only read posts, but can not create posts or topics by yourself. To be able to post you need to register. Then you can participate in the community active and use many member-only features such as customizing your profile, sending personal messages, and voting in polls. Registration is simple, fast, and completely free.

Join our community!

If you are already a member please log in to your account to access all of our features:

Username:   Password:
Add Reply
The Wonderfully Evil World of Pointers; An evil, yet necessary tool to learn C++
Topic Started: Jul 12 2010, 12:25 AM (837 Views)
Gandalf20000
Member Avatar
Geek
[ *  *  *  *  *  * ]
This is the average GM to C++ transfer works (at least for me):
Creating the first program: Wow, C++ isn't very hard! It's not much different from programming in GM!
Learning about functions: Not too hard, C++ is gonna be easy!
Reaching pointers: Huh? Wha... what? Why do I need pointers at all?

Pointers are an often confusing, yet vital component of C++. Having done a lot of C++ lately, I've finally grasped the concept of what a pointer is and what it's for.

Simply said, a pointer is the memory address where a variable is stored. The best analogy I can think of is a house. Every house contains something (possessions, people, food, etc...). This house is a variable or an instance of a class. Also, every house has an address. This address is the pointer. The address says where the house is located so that the house can be accessed.

Ok, enough for my crappy analogy. The purpose of a pointer is so you can access the original variable without having to have an instance of the object or variable in that scope. This is very useful when you start working with classes, because often multiple classes need to access the same object, but without a pointer you would need to access the same object by copying it, which often consumes more memory than a pointer, and you would be required to update it every time you want to access a member (whether a method or a variable) of that class. However, if you use a pointer, you simply create a pointer to the object, and you can access it with a much smaller memory footprint and only have to update the object itself, not the object and however many copies.

Now, for some code.
Code:
 

#include <iostream>

using namespace std;

int main(void)
{
int foo=50;
int *bar=&foo;

cout<<bar<<"\n";

system("PAUSE");
return 0;
};

Now, you might expect this code to print "50" in the command line. However, you will get something more like this: 003BFB14.
This is because you are actually printing the memory address at which the value of foo is held. Let's change the code a little bit:
Code:
 

#include <iostream>

using namespace std;

int main(void)
{
int foo=50;
int *bar=&foo;

cout<<*bar<<"\n"; //Added an asterisk before "bar."

system("PAUSE");
return 0;
};

If you did everything right, it should be returning "50" now. You're probably asking, "What happened?" You just dereferenced the pointer. There are two important operators you need to know while working with pointers:
&: The ampersand, which is the reference operator. This converts an object or a reference into a pointer.
*: The asterisk, which is the dereference operator. This, in basic terms, converts a pointer to a reference.
Now, what is a reference? A reference is almost like an object. They behave like them, but they are not objects. They are actually a memory address which refers to a value, hence being called a reference. They are basically pointers, but the syntax is different and they do not need to be dereferenced before the value they point to can be accessed.

So, let's break down the interesting code in the main function:
Code:
 

int foo=50;
int *bar=&foo;

"foo" is an integer equal to 50. Okay, that's easy. "bar" is where all the interesting stuff happens. "bar" is declared as a pointer to an integer, "foo."
Code:
 

cout<<*bar<<"\n";

This dereferences "bar," so it returns the value it points to, which is, in this case, 50, because "foo" is held at that memory address.

If you're still confused, read over everything again a few more times and mess around until you get it, because it only gets more confusing.

Another important thing you should know about pointers is that pointers and arrays are basically the same thing. Allow me to show you:
Code:
 

#include <iostream>

using namespace std;

int main(void)
{
int foo[5]={1,2,3,4,5};
int *bar=foo;

for(int i=0;i<5;i++)
{
cout<<*bar<<"\n";
bar++;
}

system("PAUSE");
return 0;
};

If you did the code right, it should type out the value of every index of "foo." This is because the "[]" operator used to designate which index to access is actually a form of the dereference operator.

There is one more operator that is often useful. It's the arrow (->), which, in the code below, will be demonstrated using a non existent class:
Code:
 

void main()
{
foo* bar=createFoo();

(*bar).a();
bar->b();
delete bar;
}

Using the arrow is the same as doing (*pointerToClass).classMember. Although not necessary, it is a nice touch because it helps to clean up your code a little bit. Rather than dereference the pointer yourself in parentheses (because of the operator precedence), which can be a headache if you're working with long equations that require an abundance of parentheses. It's not much, but it is a nice touch.

I hope my tutorial helped you out. You can also do pointers to pointers (should be self-explanatory) and void pointers (which can point to any type, but must be cast to another pointer type before it can be dereferenced). If you have any questions or comments, please feel free to post them.

Change history:
July 12, 2010: Added information about "->" operator.
July 15, 2010: Corrections made (credit to Dr. Best) to correct my use of reference and pointer interchangeably, to clarify the difference between them, and fix some code that, albeit not incorrect, was certainly not advisable and would result in a memory leak. I think this change best represents the title. :D
Edited by Gandalf20000, Jul 15 2010, 09:26 PM.
Offline Profile Quote Post Goto Top
 
Dr. Best
Member Avatar
Administrator
[ *  *  *  *  *  * ]
Hi Gandalf20000,

this is a nice tutorial for starters, but there are some things I'd like to correct.

The first thing is your nomenclature. C++ has both, pointers and references. You are referring to pointers as references.
Gandalf20000
 
&: The ampersand, which is the reference operator. This basically causes the variable to return its reference, or memory address (I will refer to it as a reference from here on).
The unary ampersand operator converts an object or a reference to a pointer. The result is a pointer, not a reference.
Gandalf20000
 
*: The asterisk, which is the dereference operator. This, in basic terms, causes a pointer to return the value of the variable it points to. This is also used to declare something as a pointer.
The unary asterix operator converts a pointer to a reference. The result is a reference, not a value. But since references are designed to behave the same way as objects, this is a very slight difference.

Since you do not appear to be familiar with the concept I will give you a quick introduction. You will certainly find more information on the web. References are declared like this:
Code:
 
int Foo=50;
int& rFoo=Foo;

A reference always has to be initialized immediately, so writing the following would not be legit:
Code:
 
int Foo=50;
int& rFoo;
rFoo=Foo;

Once declared like above rFoo will behave as if it was Foo. References are basically pointers, but the syntax is different. Pointers always need to be dereferenced before their use. For references this is not necessary. You might wonder why you would need references, if you have pointers. Like many other concepts (e.g. private attributes and const-correctness) references provide a way to restrict your own possibilities. This way you can avoid that doing things is possible, which must not be done in the first place. That is always a good thing. One example. Lets say double random(...) is supposed to be a function that computes a random number smaller than a given parameter. Since you know that on 32-bit systems pointers are smaller than doubles, you decided to pass a pointer, so your declaration is:
Code:
 
double random(const double* pMaxValue){
// Compute and return the random value
}

Somebody, who uses this function may assume that it uses a default value (e.g. 1.0), if you pass NULL, so he may write:
Code:
 
double randomPercentage=random(NULL);

If his assumption was wrong random(...) will probably cause an access violation, when it tries to work with the pointer NULL and the application will crash.

A better design would use a reference:
Code:
 
double random(const double& rMaxValue){
// Compute and return the random value
}

Now the user can not pass NULL anymore, because NULL is a pointer and can not be converted to a reference implicitly. He may write something like this:
Code:
 
double randomPercentage=random(*((double*)NULL));

But this should never be done and every good C++ programmer knows that. So the reason why references are useful is that their design makes it very hard to create invalid references. And this avoids mistakes. Besides they can ease the syntax for function calls. With the pointer implementation of random one would need to call it like this:
Code:
 
double randomPercentage=random(&1.0);

With the reference implementation you can call it like this:
Code:
 
double randomPercentage=random(1.0);

The second one is definitely nicer. You do not even need to know, whether you pass a reference or a double. If random was declared like this, it would still work:
Code:
 
double random(double MaxValue){
// Compute and return the random value
}

Another reason why references are useful is that they are inevitable for operator overloading. Operators always need to take something that looks like an object, but in many cases they can not take copies as parameters, because that would lead to unnecessary copying. References are the perfect solution.

So to sum this up here is what you should remember:

  • Pointers and references are two different things. Do not mix their names.
  • References are useful, because it is hard to create invalid references and because they behave like objects.
  • If you take a look behind the scenes pointers and references are pretty much the same thing.


The other thing I'd like to criticize is your example code on the -> operator.
Code:
 
void main()
{
foo* bar=createFoo();

(*bar).a();
bar->b();
}

This code will almost certainly lead either to an access violation (i.e. use of an invalid pointer) or to a memory leak (i.e. unfreed memory). To understand why, we need to look at possible implementations of createFoo();. The first possibility is that you create a local object and return a pointer to that object. Just like this:
Code:
 
Foo* createFoo(){
Foo newFoo;
return &newFoo;
}

If you do that you are totally screwed. newFoo is a local variable, so it gets destructed immediately, when createFoo() is left. The pointer bar in your code above, will be invalid immediately. This is likely to lead to an access violation, but that is not guaranteed. The behavior is undefined. It may be a bug that is hard to find. So you won't do that. The other possibility is the use of new. That is basically a good idea. What you do is the following:
Code:
 
Foo* createFoo(){
return new Foo();
}

Now createFoo() is not wrong by itself, but main() will lead to a memory leak. The correct code would be:
Code:
 
void main()
{
foo* bar=createFoo();

(*bar).a();
bar->b();
delete bar;
}

That code is not perfect, but in some cases it's reasonable. It is at least correct.

P.S.: Damn, it feels good to type some C++ after all this Java programming at university.
Offline Profile Quote Post Goto Top
 
Sothh
Member Avatar
Shaman Of Time
[ *  *  *  *  *  * ]
Dr. Best
Jul 14 2010, 06:19 PM
P.S.: Damn, it feels good to type some C++ after all this Java programming at university.
To be perfectly off topic, I have to take Java as well (I am majoring in Computer Software Specialist) which I find quite stupid. Java is slow, the language is not as clean as C++. Why the crap are they teaching Java and not Python?
“You can’t outrun Death forever.
But you can make the Bastard work for it.”

Major Korgo Korgar
“Last of The Lancers” - AFC 32
(Andromeda Ascendant Record Database)
Offline Profile Quote Post Goto Top
 
skarik
Member Avatar
kitten eating scum
[ *  *  *  *  *  * ]
Sothh
Jul 14 2010, 09:34 PM
Dr. Best
Jul 14 2010, 06:19 PM
P.S.: Damn, it feels good to type some C++ after all this Java programming at university.
To be perfectly off topic, I have to take Java as well (I am majoring in Computer Software Specialist) which I find quite stupid. Java is slow, the language is not as clean as C++. Why the crap are they teaching Java and not Python?
Answer: Java is easy.

May I brag that because I did the AP test I only have bear with it one semester? :P Computer engineering woooo
Blog|EHS
Offline Profile Quote Post Goto Top
 
Sothh
Member Avatar
Shaman Of Time
[ *  *  *  *  *  * ]
Synexn-Prime
Jul 15 2010, 12:54 AM
Sothh
Jul 14 2010, 09:34 PM
Dr. Best
Jul 14 2010, 06:19 PM
P.S.: Damn, it feels good to type some C++ after all this Java programming at university.
To be perfectly off topic, I have to take Java as well (I am majoring in Computer Software Specialist) which I find quite stupid. Java is slow, the language is not as clean as C++. Why the crap are they teaching Java and not Python?
Answer: Java is easy.

May I brag that because I did the AP test I only have bear with it one semester? :P Computer engineering woooo
I have not ever tried to program anything in it, but it appears easy enough. I am just dreading setting through classes that teach me a language that I will most likely never use.

I can probably pass out of a lot of the first classes as well.
“You can’t outrun Death forever.
But you can make the Bastard work for it.”

Major Korgo Korgar
“Last of The Lancers” - AFC 32
(Andromeda Ascendant Record Database)
Offline Profile Quote Post Goto Top
 
Gandalf20000
Member Avatar
Geek
[ *  *  *  *  *  * ]
Java is easy, but I find the only advantage over C++ is that it includes packages oriented towards developing a full blown application in a window quickly. However, the speed is not nearly that of even my crappy attempt at C++ programming.

We use Java in my Pre-AP Computer Science class at school. Normal or Pre-AP Computer Science is recommended to take before AP Computer Science, but the coursework between Pre-AP and AP is identical, and the only difference is the teacher gives Pre-AP more time to work on a program and they don't take the AP exam. However, this year, I'm taking AP (I want that AP credit and the math credit), but since I already know Java, my teacher basically told me I'm going to be so much further ahead of the rest of the class he wants me to build a project program every grading period (which is supposed to be six weeks, but ironically varies from five to seven) in whatever language I choose. I think it also helps that next year's class is going to be full of morons because it got advertised that AP CS was incredibly easy and could be used as the 4th math credit for graduation (I'll probably have 5 math credits when I graduate due to the AP Calculus class I intend on taking, but that's a couple years away for me). Thing they didn't know is that the Pre-AP/AP class had five guys in it, all of us smarter than the average student looking for a 4th math credit. I don't think it will be that difficult.

It's funny that they would teach Java over Python because Java is "easy," in spite of the fact that Python is so easy you can spend a weekend learning it and know almost everything about it.
Offline Profile Quote Post Goto Top
 
skarik
Member Avatar
kitten eating scum
[ *  *  *  *  *  * ]
I think it has to do with introducing object-oriented concepts early. My AP computer science teacher said that C++ was a madhouse for her after using Pascal. Then Java came the first course standard just as she was starting to figure out object-oriented programming, and so she found that awesome. I mean, if you are taught to program solely without objects then bam you have to think object-based (something Game Maker truly teaches to fuck up) - that's a huge change right there. I still really don't even know what object-oriented programming is. However, I have managed to get into this object stuff more and more, which makes things much easier: who knew that treating the keyboard as an actual object would make things so much easier?

But this is much off topic. I read the topic again, and found a use for references. Sweet.
Blog|EHS
Offline Profile Quote Post Goto Top
 
DealsFor.me - The best sales, coupons, and discounts for you
« Previous Topic · Tutorials · Next Topic »
Add Reply