Pointers and the Free Store
Finding Addresses Explicitly
-
Just apply the address operator, represented by
&, to a variable to get
its location.
-
For example, if
banana is a variable, &banana is its address.
// address.cpp -- using the & operator to find addresses
#include <iostream>
using namespace std;
int main()
{
int donuts = 6;
double cups = 4.5;
cout << "donuts value = " << donuts;
cout << " and donuts address = " << &donuts << "\n";
cout << "cups value = " << cups;
cout << " and cups address = " << &cups << "\n";
return 0;
}
OUTPUT:
donuts value = 6 and donuts address = 006AFDF4
cups value = 4.5 and cups address = 006AFDEC
What Pointers Are
-
A pointer is a special type of variable that holds the address of a value.
-
The name of the pointer represents the address of the variable.
Applying the * operator to the pointer name, we get the value stored
at that address.
int Tomato = 7; // a variable Tomato set to 7
int* pTomato; // declare a pointer "pTomato"
pTomato = &Tomato // assign the address of Tomato to the pointer
*pTomato = 8 // By applying *, we change the value of Tomato to 8.
// (i.e. Tomato is now 8)
The * operator is called the dereferencing operator.
Declaring and Initializing Pointers
-
To declare a pointer to a particular type, use this form:
typeName * pointerName;
For example, int* pointerX
We say the type for pointerX is pointer-to-int, or more
concisely, int *.
-
You should assign a pointer a memory address. You can apply the
& operator
to a variable name to get an address of named memory.
-
Alternatively, you can use the
new operator to return the address of unnamed
memory.
-
A pointer variable is never simply a pointer. It always is a pointer to a specific type.
-
Golden Rule:: ALWAYS initialize a pointer to a definite and appropriate
address before you apply the dereferencing operator (
*) to it.
Pointers and Numbers
Allocating Memory with New
Freeing Memory with Delete
-
The
delete operator enables you to return memory to the memory pool when you
are finished with it. Memory that you return, or free, then can be reused by
other parts of your program.
-
You should always balance a use of
new with a use of delete;
otherwise, you can wind up with a memory leak, that is, memory that has been
allocated but no longer ca be used.
-
You should not attempt to free a block of memory that you already have freed, as the
result of such an action is undefined.
-
Use
delete only to free memory allocated with new. However, it
is safe to apply delete to a null pointer.
Creating Dynamic Arrays
Static Binding
-
If you create an array by declaring it, the space is allocated when the program is
compiled. Whether or not the program finally uses the array, the array is there, using up
memory. Allocating the array during compile time is called static binding,
meaning the array is bult into the program at compilation time.
Dynamic Binding
-
But with
new, you can create an array during run time if you need it and
skip creating the array if you don't need it. Or, you can select an array size after
the program is running. This is called dynamic binding, meaning that the array
is created while the program is running.
-
Such an array is called a dynamic array. With static binding, you must specify
the array size when you write the program. With dynamic binding, the program can decide
upion an array size while the program runs.
Creating Dynamic Arrays
-
The general form for allocating and assigning memory for an array is this:
type_name pointer_name = new type_name[num_elements];
E.g. if you need an array of 10 ints, do this:
int* psome = new int[10]; // get a block of 10 ints
-
You should use an alternative form of
delete that indicates you are freeing
an array:
delete [] psome; // free a dynamic array
Rules when using new and delete
-
Don't use
delete to free memory that new didn't allocate.
-
Don't use
delete to free the same block of memory twice in succession.
-
Use
delete [] if you used new [] to allocate an array.
-
Use
delete (no brackets) if you used new to allocate a single
entity.
-
It's safe to apply
delete to the null pointer (nothing happens).
Using a Dynamic Array
-
If
psome points to the first element of the array, *psome is the
value of the first element.
-
You can use
psome[0] instead of *psome for the first element,
psome[1] for the second element, and so on.
-
The reason you can do this is that C and C++ handle arrays internally by using pointers,
and arrays and pointers are nearly equivalent.
Pointers, Arrays, and Pointer Arithmetic
-
In most contexts, C++ interprets the name of an array as the address of it first element.
Hence, if we have a
wages array, the statement
double * pw = wages;
makes pw a pointer to type double and then initializes pw
to wages, which is the address of the first element of the
wages array. So:
wages = &wages[0] = address of first element of array
-
Also, in general,
arrayname[i] = *(arrayname + i)
If you use a pointer instead of an array, pointername[i] = *(pointername + i)
int * pi = new int[10]; // pi points to block of 10 ints
*pi = 5; // set zero element to 5
pi[0] = 6; // reset zero element to 6
pi[9] = 44; // set tenth element to 44
int tacos[10];
*(tacos + 4) = 12; // set tacos[4] to 12
Pointers and Strings
Links
http://www.thecodeproject.com/cpp/pointers.asp
http://www.gamedev.net/reference/articles/article1697.asp