181 likes | 303 Views
Pointers. A pointer variable holds an address We may add or subtract an integer to get a different address. Adding an integer k to a pointer p with base type t will make the value of p equal to p+k*sizeof(t) Example: int *ptr; int arr[4] = {1,2,3,4};
E N D
Pointers • A pointer variable holds an address • We may add or subtract an integer to get a different address. • Adding an integer k to a pointer p with base type t will make the value of p equal to p+k*sizeof(t) • Example: int *ptr; int arr[4] = {1,2,3,4}; ptr = arr + 2; // equivalent to ptr = &(arr[2]);
Pointers • A pointer variable holds an address • We can access the contents at that address by using the dereferencing operator, * • Do not confuse this with the multiplication operator or with the asterisk used in the pointer's declaration. • Example: int *pum, number; pnum = & number; *pnum = 16; cout << number << endl; // this prints 16 • NEVER dereference an uninitialized pointer
Pointers & functions • Pointers allow us to implement pass by reference. void swap(int *a, int *b) { int temp =* a; *a = *b; *b = temp; } int main () { int x = 3, y = 5; swap(&x, &y); return 0; } void swap(int &a, int &b) { int temp = a; a = b; b = temp; } int main () { int x = 3, y = 5; swap(x ,y); return 0; }
Pointers & functions • Function arguments that are pointers • copy an address to the formal parameters • Dereferencing the formal parameter lets us modify the value pointed to by the pointer. • But changing the pointer itself NEVER changes the actual parameter • Example 1: void initialize (int *ptr) { *ptr = 34; } int main () { int x, *px; px = &x; initialize(px); return 0; } here x has become 34
Pointers & functions • Function arguments that are pointers • copy an address to the formal parameters • Dereferencing the formal parameter lets us modify the value pointed to by the pointer. • But changing the pointer itself NEVER changes the actual parameter • Example 2: void initialize (int *ptr) { *ptr = 34; ptr++; } int main () { int x, *px; px = &x; initialize(px); return 0; } here x has become 34 but px is unchanged.
Pointers & functions • Be very careful with functions that return pointers. Make certain that the pointer points to something valid on return and that space has been properly allocated. • Example: int * func () { int x, *p; x = 10; p = &x; return p; } int main () { int *ptr ; ptr = func(); cout << *ptr << endl; return 0; } This program will print out garbage. Why? p and x are local variables, statically stored in func()'s stack frame. They "disappear" on exit from func(), so *ptr cannot contain the value of x.
More on pass by reference • When an argument is passed by value, enough memory must be allocated for a copy of that argument. This may slow down our program if the argument is a large object. • The solution is to pass it by reference. HOWEVER, we may not want to allow the function to modify the value of the argument. • In that case, we must use the keyword const to specify that the argument cannot be changed. • This can be done with references, arrays and pointers.
More on pass by reference • Example 1: struct bigTypeT { ... }; void func (const bigTypeT &arg) { // arg cannot be modified } int main () { bigTypeT arg; func(arg); return 0; }
More on pass by reference • Example 2: void func (const int arr[]) { // arr cannot be modified } int main () { int arr[10]; func(arr); return 0; }
More on pass by reference • Example 2: void func (const int *ptr) { // *ptr cannot be modified // ptr can be modified but this will have no effect in main() // since ptr is local to func() } int main () { int *pnum, x; pnum = &x; func(pnum); return 0; }
Pointers vs. arrays • The name of an array represents the address where the array begins. • In other words, the name of an array is a pointer • HOWEVER, it is a constant pointer. • Pointer variables allow greater flexibility int numbers[10], list[10]; numbers = list; ILLEGAL!
Pointers vs. arrays • The size of an array must be specified at compile-time and is constant. • Pointers allow greater flexibility: we may use pointers to create array-like structures whose size is determined dynamically. • Goal : • allocate a chunk of memory (size determined at run time) • get its address • Tool: • the function new allocates space • The function delete deallocates space that was allocated using new
Dynamic allocation • Example 1: allocate memory to hold one integer int *pnum; // Declare pointer pnum = new int; // new allocates 4 bytes and returns // the address at that location. The // address is assigned to pnum *pnum = 32; delete pnum; // ALWAYS deallocate dynamically // allocated space to avoid memory leaks
Dynamic allocation • Example 2: allocate memory to hold one integer and initialize the integer to 32 int *pnum; pnum = new int(32); cout << *pnum; // This prints 32 delete pnum; // ALWAYS deallocate dynamically // allocated space to avoid memory leaks
Dynamic allocation • Example 3: allocate memory to hold several integers. int *pnums; cout << "How big an array do you want? "; cin >> size; pnums = new int [ size ] ; // note the brackets. // This allocates size*4 bytes for (int i = 0; i < size; i++) *(pnums+i) = 0; // This initializes all elements of the // dynamic array to zero. delete pnums; // ALWAYS deallocate dynamically // allocated space to avoid memory leaks
NULL pointers • NULL represents a special location in memory that is guaranteed to NOT contain valid data • Dereferencing a NULL pointer will cause a segmentation fault. • Programmers often initialize pointers to NULL to "catch" any unintended dereferencing of a pointer that does not contain valid data. • In some compilers, new returns NULL if it fails to allocate memory.
delete • Never try to deallocate the same memory twice • Example: int *pnum, *pcopy; pnum = new int(32); pcopy = pnum; delete pnum; delete pcopy; // ERROR! This space has already been deallocated
delete • The argument to delete should always be the address where the allocated space begins. • Example: int *pnum, *pcopy; pnum = new int(32); pcopy = pnum; pnum ++; delete pcopy; // CORRECT! delete pnum; // WRONG! pnum does not point to the beginning of // the allocated space any longer.