general
- a pointer uniquely identifies some piece of memory in your program
- allows you fine control of memory usage
- you can give any value to a pointer, but it will not check if it is valid or exists
- will turn into a runtime error
- you must
deallocate
the memory youallocate
for a pointer when you are done with it - pointers can have any dataType
- you should assign
NULL
to your pointers- points to the first location in memory which is
0
- cannot place anything at this location
- points to the first location in memory which is
- place the
*
next to the variable name for clarityint *a, b
will only assigna
as a pointer
- when
&
is used outside of a function argument it will return a memory address- can be assigned to a pointer
int *ptr = &variable;
- this is called
aliasing
since both point to the same place in memory, avoid most times
why pointers
- for creating dynamic arrays
- data structures that grow and shrink as the program runs
- linked lists, trees, graphs
details
new
keyword creates a place in memory for dynamic memoryint *ptr = new int;
dereferencing
places a value within the memory area that the pointer points to*ptr = 10;
deallocate
after you are done with memory, must tell the program it is okay to overwrite that area againdelete ptr;
- the variable still exists, and the value it is referenced to still exists
- DO NOT dereference after deleting!
- set to variable
NULL
after deallocation for safety
- is placed back in heap for reuse
- local variables (including pointers) are released after function ends
- does not include dynamic memory release though
- can reuse the variable though and set a
new
value in itptr = new int; *ptr = 4;
allocating arrays dynamically
- a pointer can point to one item or the first of many
- arrays start at
0
because you add0
to the pointer memory address to receive the first value, and add more after that- add
1
to get the second value
- add
char *name = new char[variable];
how to create a dynamic arraydelete []char;
to clean up
// we still need some size cutoff for input
// but temporarily inside the function!
char temp[100];
char *name;
cin.get(temp, 100, '\n');
cin.ignore(100, '\n');
name = new char[strlen(temp) + 1];
strcpy(name, temp);
// later
...
delete []name;
pointer math
- accessing array values is the same as adding to the pointer
a[5] == *(a+5) == 5[a] == *(5+a)
- adding to a pointer gets you the next increment of dataType
int
dataType increments by the size of anint
in memory, which is different than a character or boolean
int *a = new int[10];
int *b = new int[10];
for(int i = 0; i < 10; ++i) {
a[i] = i;
b[i] = 100*i;
}
// c is the address of the first element of the array a
for(c = a; c < a+10; c++) cout << *c << endl;
// does the exact same thing
for(int i = 0; i < 10; ++i) cout << a[i] << endl;
array[i] == *(array + i) == i[array]
char *ptr = new char[6];
strcpy(ptr, "hello");
cout << ptr << endl; // 'hello'
cout << *ptr << endl; // 'h'
cout << *(ptr++) << endl; // 'h' moves pointer over
cout << *ptr << endl; // 'e'
cout << *(++ptr) << endl; // 'l' moves pointer over
cout << ++(*ptr) << endl; // 'm' (updates the value inside of ptr)
cout << ++ptr << endl; // 'lo' moves the pointer over
dynamic structs
- cannot access pointer struct members with dot notation
*ptr.item
not allowed (means*(ptr.item)
)- obtain the item, then go to the address that pointer points to (ew)
ptr->item
or(*ptr).item
is how we do it- go to the address that ptr points to, then obtain the item
- this is because
*
and.
have same operator precedence, and c++ reads right to left, so parenthesis are required
- pointers are their own type
->
is the indirect access operator- left side must always have the
pointer
type - right side can only be
struct
orobject
- must NOT be
NULL
, will become a seg fault
- left side must always have the
dynamic arrays of structs
- access the struct / class member with dot notation within the array
product *ptr = new product[size];
// access this way
// does a * operation implicitly
// this is an object, so don't use '->'
ptr[0].item
pointers and functions
- can pass as an argument to functions via reference or value
- but careful, can still manipulate a pointer value when passed by value
void inc1(int x) { ++x; }
void inc2(int *x) { ++(*x); x = NULL; } // changes the copy and does not blow up
void inc3(int &x) { ++x; } // similar to inc2
// order of '*' and '&' is IMPORTANT
void inc4(int* &x) { ++(*x); x = NULL; } // will allow you to change the actual value the pointer points to because it was passed by reference
int main() {
int a = 1;
int *b = new int;
*b = 1;
int1(a) // 1
int2(&a); // 2 does not change the type of the argument, passes the reference of the value
int3(a) // 2
int4(b) // 2 passing in the address of the address
cout << a << endl;
cout << *b << endl;
}
- passing pointer by value is most common
- requires use of
->
with struct / object
- requires use of
- utilize a temporary array to read input, then use dynamic pointer array to copy user input into
p = new product;
p->item = new char[strlen(tempArray) + 1];
strcpy(p->item, temp);
pointers as members
struct movie {
char title[100];
int rating;
}
class list {
public:
list();
list(int);
// a destructor for clean up (needed for pointers)
// cannot take any arguments, never manually invoked
~list();
int add(const movie&);
int remove(char title[]);
int displayAll();
private:
movie *myList; // not yet an array, but treating as such
int moveListSize;
int numberOfVideos;
}
// in main.cpp
list::list() {
myList = NULL; // initialize
movieListSize = 0;
numberOfVideos = 0;
}
// gives a default value
// will then not need empty constructor
list::list(int size = 100) {
myList = new movie[size]; // initialize
movieListSize = size;
numberOfVideos = 0;
}
list::~list() {
// clean up!
// '[]' delete all cells of the array
// if you forget to do this on an array, will only free up the first position
delete [] myList;
// set it to null since it will still point to something, but no longer what we think it does!
myList = NULL;
}